1 7 8 package java.awt; 9 10 import java.awt.font.FontRenderContext ; 11 import java.awt.font.GlyphVector ; 12 import java.awt.font.LineMetrics ; 13 import java.awt.font.TextAttribute ; 14 import java.awt.font.TextLayout ; 15 import java.awt.font.TransformAttribute ; 16 import java.awt.geom.AffineTransform ; 17 import java.awt.geom.Rectangle2D ; 18 import java.awt.peer.FontPeer; 19 import java.io.*; 20 import java.lang.ref.SoftReference ; 21 import java.text.AttributedCharacterIterator.Attribute; 22 import java.text.CharacterIterator ; 23 import java.text.StringCharacterIterator ; 24 import java.util.HashMap ; 25 import java.util.Hashtable ; 26 import java.util.Locale ; 27 import java.util.Map ; 28 import sun.font.StandardGlyphVector; 29 import sun.java2d.FontSupport; 30 31 import sun.font.Font2D; 32 import sun.font.Font2DHandle; 33 import sun.font.FontManager; 34 import sun.font.GlyphLayout; 35 import sun.font.FontLineMetrics; 36 import sun.font.CoreMetrics; 37 38 136 public class Font implements java.io.Serializable 137 { 138 139 static { 140 141 Toolkit.loadLibraries(); 142 initIDs(); 143 } 144 145 152 private Hashtable fRequestedAttributes; 153 154 private static final Map EMPTY_MAP = new Hashtable (5, (float)0.9); 155 private static final TransformAttribute IDENT_TX_ATTRIBUTE = 156 new TransformAttribute (new AffineTransform ()); 157 158 162 163 166 public static final int PLAIN = 0; 167 168 172 public static final int BOLD = 1; 173 174 178 public static final int ITALIC = 2; 179 180 183 public static final int ROMAN_BASELINE = 0; 184 185 189 public static final int CENTER_BASELINE = 1; 190 191 195 public static final int HANGING_BASELINE = 2; 196 197 203 204 public static final int TRUETYPE_FONT = 0; 205 206 212 public static final int TYPE1_FONT = 1; 213 214 222 protected String name; 223 224 232 protected int style; 233 234 241 protected int size; 242 243 250 protected float pointSize; 251 252 255 private transient FontPeer peer; 256 private transient long pData; private transient Font2DHandle font2DHandle; 258 private transient int superscript; 259 private transient float width = 1f; 260 261 265 private transient boolean createdFont = false; 266 267 private transient double[] matrix; 269 private transient boolean nonIdentityTx; 270 271 private static final AffineTransform identityTx = new AffineTransform (); 272 275 private static final long serialVersionUID = -4206021311591459213L; 276 277 283 @Deprecated 284 public FontPeer getPeer(){ 285 return getPeer_NoClientCode(); 286 } 287 final FontPeer getPeer_NoClientCode() { 292 if(peer == null) { 293 Toolkit tk = Toolkit.getDefaultToolkit(); 294 this.peer = tk.getFontPeer(name, style); 295 } 296 return peer; 297 } 298 299 300 private Hashtable getRequestedAttributes() { 301 if (fRequestedAttributes == null) { 302 fRequestedAttributes = new Hashtable (7, (float)0.9); 303 fRequestedAttributes.put(TextAttribute.TRANSFORM, 304 IDENT_TX_ATTRIBUTE); 305 fRequestedAttributes.put(TextAttribute.FAMILY, name); 306 fRequestedAttributes.put(TextAttribute.SIZE, new Float (size)); 307 fRequestedAttributes.put(TextAttribute.WEIGHT, 308 (style & BOLD) != 0 ? 309 TextAttribute.WEIGHT_BOLD : 310 TextAttribute.WEIGHT_REGULAR); 311 fRequestedAttributes.put(TextAttribute.POSTURE, 312 (style & ITALIC) != 0 ? 313 TextAttribute.POSTURE_OBLIQUE : 314 TextAttribute.POSTURE_REGULAR); 315 fRequestedAttributes.put(TextAttribute.SUPERSCRIPT, 316 new Integer (superscript)); 317 fRequestedAttributes.put(TextAttribute.WIDTH, 318 new Float (width)); 319 } 320 return fRequestedAttributes; 321 } 322 323 private void initializeFont(Hashtable attributes) { 324 if (attributes != null) { 325 Object obj = attributes.get(TextAttribute.TRANSFORM); 326 if (obj instanceof TransformAttribute ) { 327 nonIdentityTx = !((TransformAttribute )obj).isIdentity(); 328 } else if (obj instanceof AffineTransform ) { 329 nonIdentityTx = !((AffineTransform )obj).isIdentity(); 330 } 331 332 obj = attributes.get(TextAttribute.SUPERSCRIPT); 333 if (obj instanceof Integer ) { 334 superscript = ((Integer )obj).intValue(); 335 336 nonIdentityTx |= superscript != 0; 338 } 339 340 obj = attributes.get(TextAttribute.WIDTH); 341 if (obj instanceof Integer ) { 342 width = ((Float )obj).floatValue(); 343 344 nonIdentityTx |= width != 1; 346 } 347 } 348 } 349 350 private Font2D getFont2D() { 351 if (FontManager.usingPerAppContextComposites && 352 font2DHandle != null && 353 font2DHandle.font2D instanceof sun.font.CompositeFont && 354 ((sun.font.CompositeFont)(font2DHandle.font2D)).isStdComposite()) { 355 return FontManager.findFont2D(name, style, 356 FontManager.LOGICAL_FALLBACK); 357 } else if (font2DHandle == null) { 358 font2DHandle = 359 FontManager.findFont2D(name, style, 360 FontManager.LOGICAL_FALLBACK).handle; 361 } 362 366 return font2DHandle.font2D; 367 } 368 369 376 private Font2DHandle getFont2DHandleForCreatedFont() { 377 if (font2DHandle != null && createdFont && 378 !(font2DHandle.font2D instanceof sun.font.CompositeFont)) { 379 return font2DHandle; 380 } else { 381 return null; 382 } 383 } 384 385 433 public Font(String name, int style, int size) { 434 this.name = (name != null) ? name : "Default"; 435 this.style = (style & ~0x03) == 0 ? style : 0; 436 this.size = size; 437 this.pointSize = size; 438 } 439 440 private Font(String name, int style, float sizePts) { 441 this.name = (name != null) ? name : "Default"; 442 this.style = (style & ~0x03) == 0 ? style : 0; 443 this.size = (int)(sizePts + 0.5); 444 this.pointSize = sizePts; 445 } 446 447 448 private Font(File fontFile, int fontFormat, boolean isCopy) 449 throws FontFormatException { 450 this.createdFont = true; 451 454 this.font2DHandle = 455 FontManager.createFont2D(fontFile, fontFormat, isCopy).handle; 456 this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault()); 457 this.style = Font.PLAIN; 458 this.size = 1; 459 this.pointSize = 1f; 460 } 461 462 private Font(Map attributes, boolean created, Font2DHandle handle) { 463 this.createdFont = created; 464 467 if (created) { 468 this.font2DHandle = handle; 469 } 470 initFromMap(attributes); 471 } 472 473 482 public Font(Map <? extends Attribute , ?> attributes) { 483 initFromMap(attributes); 484 } 485 486 487 private void initFromMap(Map attributes) { 488 this.name = "Dialog"; 489 this.pointSize = 12; 490 this.size = 12; 491 492 if((attributes != null) && 493 (!attributes.equals(EMPTY_MAP))) 494 { 495 Object obj; 496 fRequestedAttributes = new Hashtable (attributes); 497 if ((obj = attributes.get(TextAttribute.FAMILY)) != null) { 498 this.name = (String )obj; 499 } 500 501 if ((obj = attributes.get(TextAttribute.WEIGHT)) != null) { 502 if(obj.equals(TextAttribute.WEIGHT_BOLD)) { 503 this.style |= BOLD; 504 } 505 } 506 507 if ((obj = attributes.get(TextAttribute.POSTURE)) != null) { 508 if(obj.equals(TextAttribute.POSTURE_OBLIQUE)) { 509 this.style |= ITALIC; 510 } 511 } 512 513 if ((obj = attributes.get(TextAttribute.SIZE)) != null) { 514 this.pointSize = ((Float )obj).floatValue(); 515 this.size = (int)(this.pointSize + 0.5); 516 } 517 518 if ((obj = attributes.get(TextAttribute.TRANSFORM)) != null) { 519 if (obj instanceof TransformAttribute ) { 520 nonIdentityTx = !((TransformAttribute )obj).isIdentity(); 521 } else if (obj instanceof AffineTransform ) { 522 nonIdentityTx = !((AffineTransform )obj).isIdentity(); 523 } 524 } 525 526 if ((obj = attributes.get(TextAttribute.SUPERSCRIPT)) != null) { 527 if (obj instanceof Integer ) { 528 superscript = ((Integer )obj).intValue(); 529 nonIdentityTx |= superscript != 0; 530 } 531 } 532 533 if ((obj = attributes.get(TextAttribute.WIDTH)) != null) { 534 if (obj instanceof Float ) { 535 width = ((Float )obj).floatValue(); 536 nonIdentityTx |= width != 1; 537 } 538 } 539 } 540 } 541 542 552 public static Font getFont(Map <? extends Attribute , ?> attributes) { 553 Font font = (Font )attributes.get(TextAttribute.FONT); 554 if (font != null) { 555 return font; 556 } 557 558 return get(new Key(attributes)); 559 } 560 561 private static SoftReference cacheRef = new SoftReference (new HashMap ()); 562 private static Font get(Key key) { 563 Font f = null; 564 Map cache = (Map )cacheRef.get(); 565 if (cache == null) { 566 cache = new HashMap (); 567 cacheRef = new SoftReference (cache); 568 } else { 569 f = (Font )cache.get(key); 570 } 571 572 if (f == null) { 573 f = new Font (key.attrs); 574 cache.put(key, f); 575 } 576 577 return f; 578 } 579 580 585 private static class Key { 586 String family = "Dialog"; float weight = 1.0f; 588 float posture = 0.0f; 589 float size = 12.0f; 590 int superscript = 0; 591 float width = 1.0f; 592 double[] txdata = null; 594 Map attrs; 595 int hashCode = 0; 596 597 Key(Map map) { 598 attrs = map; 599 600 Object o = map.get(TextAttribute.FAMILY); 601 if (o != null) { 602 family = (String )o; 603 } 604 hashCode = family.hashCode(); 605 606 o = map.get(TextAttribute.WEIGHT); 607 if (o != null && o != TextAttribute.WEIGHT_REGULAR) { 608 float xweight = ((Float )o).floatValue(); 611 if (xweight == TextAttribute.WEIGHT_BOLD.floatValue()) { 612 weight = xweight; 613 hashCode = (hashCode << 3) ^ Float.floatToIntBits(weight); 614 } 615 } 616 617 o = map.get(TextAttribute.POSTURE); 618 if (o != null && o != TextAttribute.POSTURE_REGULAR) { 619 float xposture = ((Float )o).floatValue(); 621 if (xposture == TextAttribute.POSTURE_OBLIQUE.floatValue()) { 622 posture = xposture; 623 hashCode = (hashCode << 3) ^ Float.floatToIntBits(posture); 624 } 625 } 626 627 o = map.get(TextAttribute.SIZE); 628 if (o != null) { 629 size = ((Float )o).floatValue(); 630 if (size != 12.0f) { 631 hashCode = (hashCode << 3) ^ Float.floatToIntBits(size); 632 } 633 } 634 635 o = map.get(TextAttribute.TRANSFORM); 636 if (o != null) { 637 AffineTransform tx = null; 638 if (o instanceof TransformAttribute ) { 639 TransformAttribute ta = (TransformAttribute )o; 640 if (!ta.isIdentity()) { 641 tx = ta.getTransform(); 642 } 643 } else if (o instanceof AffineTransform ) { 644 AffineTransform at = (AffineTransform )o; 645 if (!at.isIdentity()) { 646 tx = at; 647 } 648 } 649 if (tx != null) { 650 txdata = new double[6]; 651 tx.getMatrix(txdata); 652 hashCode = (hashCode << 3) ^ new Double (txdata[0]).hashCode(); 653 } 654 } 655 656 o = map.get(TextAttribute.SUPERSCRIPT); 657 if (o != null) { 658 if (o instanceof Integer ) { 659 superscript = ((Integer )o).intValue(); 660 hashCode = hashCode << 3 ^ superscript; 661 } 662 } 663 664 o = map.get(TextAttribute.WIDTH); 665 if (o != null) { 666 if (o instanceof Float ) { 667 width = ((Float )o).floatValue(); 668 hashCode = hashCode << 3 ^ Float.floatToIntBits(width); 669 } 670 } 671 } 672 673 public int hashCode() { 674 return hashCode; 675 } 676 677 public boolean equals(Object rhs) { 678 Key rhskey = (Key)rhs; 679 if (this.hashCode == rhskey.hashCode && 680 this.size == rhskey.size && 681 this.weight == rhskey.weight && 682 this.posture == rhskey.posture && 683 this.superscript == rhskey.superscript && 684 this.width == rhskey.width && 685 this.family.equals(rhskey.family) && 686 ((this.txdata == null) == (rhskey.txdata == null))) { 687 688 if (this.txdata != null) { 689 for (int i = 0; i < this.txdata.length; ++i) { 690 if (this.txdata[i] != rhskey.txdata[i]) { 691 return false; 692 } 693 } 694 } 695 return true; 696 } 697 return false; 698 } 699 } 700 701 702 724 public static Font createFont(int fontFormat, InputStream fontStream) 725 throws java.awt.FontFormatException , java.io.IOException { 726 727 if (fontFormat != Font.TRUETYPE_FONT && 728 fontFormat != Font.TYPE1_FONT) { 729 throw new IllegalArgumentException ("font format not recognized"); 730 } 731 final InputStream fStream = fontStream; 732 Object ret = java.security.AccessController.doPrivileged( 733 new java.security.PrivilegedAction () { 734 public Object run() { 735 File tFile = null; 736 try { 737 tFile = File.createTempFile("+~JF", ".tmp", null); 738 tFile.deleteOnExit(); 739 BufferedInputStream inStream = 740 new BufferedInputStream(fStream); 741 FileOutputStream outStream = new FileOutputStream(tFile); 742 int bytesRead = 0; 743 int bufSize = 8192; 744 byte [] buf = new byte[bufSize]; 745 while (bytesRead != -1) { 746 bytesRead = inStream.read(buf, 0, bufSize); 747 if (bytesRead != -1) { 748 outStream.write(buf, 0, bytesRead); 749 } 750 } 751 752 outStream.close(); 753 } catch (IOException e) { 754 return e; 755 } 756 return tFile; 757 } 758 }); 759 760 if (ret instanceof File) { 761 return new Font ((File)ret, fontFormat, true); 762 } else if (ret instanceof IOException) { 763 throw (IOException)ret; 764 } else { 765 throw new FontFormatException ("Couldn't access font stream"); 766 } 767 } 768 769 797 public static Font createFont(int fontFormat, File fontFile) 798 throws java.awt.FontFormatException , java.io.IOException { 799 if (fontFormat != Font.TRUETYPE_FONT && 800 fontFormat != Font.TYPE1_FONT) { 801 throw new IllegalArgumentException ("font format not recognized"); 802 } 803 SecurityManager sm = System.getSecurityManager(); 804 if (sm != null) { 805 FilePermission filePermission = 806 new FilePermission(fontFile.getPath(), "read"); 807 sm.checkPermission(filePermission); 808 } 809 if (!fontFile.canRead()) { 810 throw new IOException("Can't read " + fontFile); 811 } 812 return new Font (fontFile, fontFormat, false); 813 } 814 815 821 public AffineTransform getTransform() { 822 835 if (nonIdentityTx) { 836 AffineTransform at = null; 837 Object obj = getRequestedAttributes().get(TextAttribute.TRANSFORM); 838 if (obj != null) { 839 if( obj instanceof TransformAttribute ){ 840 at = ((TransformAttribute )obj).getTransform(); 841 } 842 else { 843 if ( obj instanceof AffineTransform ){ 844 at = new AffineTransform ((AffineTransform )obj); 845 } 846 } 847 } else { 848 at = new AffineTransform (); 849 } 850 851 if (superscript != 0) { 852 double trans = 0; 855 int n = 0; 856 boolean up = superscript > 0; 857 int sign = up ? -1 : 1; 858 int ss = up ? superscript : -superscript; 859 860 while ((ss & 7) > n) { 861 int newn = ss & 7; 862 trans += sign * (ssinfo[newn] - ssinfo[n]); 863 ss >>= 3; 864 sign = -sign; 865 n = newn; 866 } 867 trans *= pointSize; 868 double scale = Math.pow(2./3., n); 869 870 at.preConcatenate(AffineTransform.getTranslateInstance(0, trans)); 871 at.scale(scale, scale); 872 873 } 886 887 if (width != 1f) { 888 at.scale(width, 1f); 889 } 890 891 return at; 892 } 893 894 return new AffineTransform (); 895 } 896 897 904 908 private static final float[] ssinfo = { 909 0.0f, 910 0.375f, 911 0.625f, 912 0.7916667f, 913 0.9027778f, 914 0.9768519f, 915 1.0262346f, 916 1.0591564f, 917 }; 918 919 938 public String getFamily() { 939 return getFamily_NoClientCode(); 940 } 941 final String getFamily_NoClientCode() { 947 return getFamily(Locale.getDefault()); 948 } 949 950 969 public String getFamily(Locale l) { 970 if (l == null) { 971 throw new NullPointerException ("null locale doesn't mean default"); 972 } 973 return getFont2D().getFamilyName(l); 974 } 975 976 984 public String getPSName() { 985 return getFont2D().getPostscriptName(); 986 } 987 988 998 public String getName() { 999 return name; 1000 } 1001 1002 1013 public String getFontName() { 1014 return getFontName(Locale.getDefault()); 1015 } 1016 1017 1028 public String getFontName(Locale l) { 1029 if (l == null) { 1030 throw new NullPointerException ("null locale doesn't mean default"); 1031 } 1032 return getFont2D().getFontName(l); 1033 } 1034 1035 1044 public int getStyle() { 1045 return style; 1046 } 1047 1048 1070 public int getSize() { 1071 return size; 1072 } 1073 1074 1082 public float getSize2D() { 1083 return pointSize; 1084 } 1085 1086 1095 public boolean isPlain() { 1096 return style == 0; 1097 } 1098 1099 1108 public boolean isBold() { 1109 return (style & BOLD) != 0; 1110 } 1111 1112 1121 public boolean isItalic() { 1122 return (style & ITALIC) != 0; 1123 } 1124 1125 1135 public boolean isTransformed() { 1136 return nonIdentityTx; 1137 } 1138 1139 1154 public static Font getFont(String nm) { 1155 return getFont(nm, null); 1156 } 1157 1158 1231 public static Font decode(String str) { 1232 String fontName = str; 1233 String styleName = ""; 1234 int fontSize = 12; 1235 int fontStyle = Font.PLAIN; 1236 1237 if (str == null) { 1238 return new Font ("Dialog", fontStyle, fontSize); 1239 } 1240 1241 int lastHyphen = str.lastIndexOf('-'); 1242 int lastSpace = str.lastIndexOf(' '); 1243 char sepChar = (lastHyphen > lastSpace) ? '-' : ' '; 1244 int sizeIndex = str.lastIndexOf(sepChar); 1245 int styleIndex = str.lastIndexOf(sepChar, sizeIndex-1); 1246 int strlen = str.length(); 1247 1248 if (sizeIndex > 0 && sizeIndex+1 < strlen) { 1249 try { 1250 fontSize = 1251 Integer.valueOf(str.substring(sizeIndex+1)).intValue(); 1252 if (fontSize <= 0) { 1253 fontSize = 12; 1254 } 1255 } catch (NumberFormatException e) { 1256 1258 styleIndex = sizeIndex; 1259 sizeIndex = strlen; 1260 if (str.charAt(sizeIndex-1) == sepChar) { 1261 sizeIndex--; 1262 } 1263 } 1264 } 1265 1266 if (styleIndex >= 0 && styleIndex+1 < strlen) { 1267 styleName = str.substring(styleIndex+1, sizeIndex); 1268 styleName = styleName.toLowerCase(Locale.ENGLISH); 1269 if (styleName.equals("bolditalic")) { 1270 fontStyle = Font.BOLD | Font.ITALIC; 1271 } else if (styleName.equals("italic")) { 1272 fontStyle = Font.ITALIC; 1273 } else if (styleName.equals("bold")) { 1274 fontStyle = Font.BOLD; 1275 } else if (styleName.equals("plain")) { 1276 fontStyle = Font.PLAIN; 1277 } else { 1278 1281 styleIndex = sizeIndex; 1282 if (str.charAt(styleIndex-1) == sepChar) { 1283 styleIndex--; 1284 } 1285 } 1286 fontName = str.substring(0, styleIndex); 1287 1288 } else { 1289 int fontEnd = strlen; 1290 if (styleIndex > 0) { 1291 fontEnd = styleIndex; 1292 } else if (sizeIndex > 0) { 1293 fontEnd = sizeIndex; 1294 } 1295 if (fontEnd > 0 && str.charAt(fontEnd-1) == sepChar) { 1296 fontEnd--; 1297 } 1298 fontName = str.substring(0, fontEnd); 1299 } 1300 1301 return new Font (fontName, fontStyle, fontSize); 1302 } 1303 1304 1323 public static Font getFont(String nm, Font font) { 1324 String str = null; 1325 try { 1326 str =System.getProperty(nm); 1327 } catch(SecurityException e) { 1328 } 1329 if (str == null) { 1330 return font; 1331 } 1332 return decode ( str ); 1333 } 1334 1335 1336 1341 public int hashCode() { 1342 return name.hashCode() ^ style ^ size; 1343 } 1344 1345 1355 public boolean equals(Object obj) { 1356 if (obj == this) { 1357 return true; 1358 } 1359 1360 if (obj != null) { 1361 try { 1362 Font font = (Font )obj; 1363 if ((size == font.size) && 1364 (pointSize == font.pointSize) && 1365 (style == font.style) && 1366 (superscript == font.superscript) && 1367 (width == font.width) && 1368 name.equals(font.name)) { 1369 1370 double[] thismat = this.getMatrix(); 1371 double[] thatmat = font.getMatrix(); 1372 1373 return thismat[0] == thatmat[0] 1374 && thismat[1] == thatmat[1] 1375 && thismat[2] == thatmat[2] 1376 && thismat[3] == thatmat[3] 1377 && thismat[4] == thatmat[4] 1378 && thismat[5] == thatmat[5]; 1379 } 1380 } 1381 catch (ClassCastException e) { 1382 } 1383 } 1384 return false; 1385 } 1386 1387 1394 public String toString() { 1397 String strStyle; 1398 1399 if (isBold()) { 1400 strStyle = isItalic() ? "bolditalic" : "bold"; 1401 } else { 1402 strStyle = isItalic() ? "italic" : "plain"; 1403 } 1404 1405 return getClass().getName() + "[family=" + getFamily() + ",name=" + name + ",style=" + 1406 strStyle + ",size=" + size + "]"; 1407 } 1409 1410 1419 1424 private int fontSerializedDataVersion = 1; 1425 1426 1433 private void writeObject(java.io.ObjectOutputStream s) 1434 throws java.lang.ClassNotFoundException , 1435 java.io.IOException 1436 { 1437 s.defaultWriteObject(); 1438 } 1439 1440 1448 private void readObject(java.io.ObjectInputStream s) 1449 throws java.lang.ClassNotFoundException , 1450 java.io.IOException 1451 { 1452 s.defaultReadObject(); 1453 if (pointSize == 0) { 1454 pointSize = (float)size; 1455 } 1456 width = 1f; initializeFont(fRequestedAttributes); 1458 } 1459 1460 1467 public int getNumGlyphs() { 1468 return getFont2D().getNumGlyphs(); 1469 } 1470 1471 1477 public int getMissingGlyphCode() { 1478 return getFont2D().getMissingGlyphCode(); 1479 } 1480 1481 1484 1486 private static double cachedMat[]; 1487 private double[] getMatrix() { 1488 if (matrix == null) { 1489 double ptSize = this.getSize2D(); 1490 if (nonIdentityTx) { 1491 AffineTransform tx = getTransform(); 1492 tx.scale(ptSize, ptSize); 1493 tx.getMatrix(matrix = new double[6]); 1494 } else { 1495 synchronized (Font .class) { 1496 double[] m = cachedMat; 1497 if (m == null || m[0] != ptSize) { 1498 cachedMat = m = 1499 new double[] {ptSize, 0, 0, ptSize, 0, 0 }; 1500 } 1501 matrix = m; 1502 } 1503 } 1504 } 1505 return matrix; 1506 } 1507 1508 1524 public byte getBaselineFor(char c) { 1525 return getFont2D().getBaselineFor(c); 1526 } 1527 1528 1534 public Map <TextAttribute ,?> getAttributes(){ 1535 return (Map <TextAttribute ,?>)getRequestedAttributes().clone(); 1536 } 1537 1538 1546 public Attribute [] getAvailableAttributes(){ 1547 Attribute attributes[] = { 1548 TextAttribute.FAMILY, 1549 TextAttribute.WEIGHT, 1550 TextAttribute.POSTURE, 1551 TextAttribute.SIZE, 1552 TextAttribute.TRANSFORM, 1553 TextAttribute.SUPERSCRIPT, 1554 TextAttribute.WIDTH, 1555 }; 1556 1557 return attributes; 1558 } 1559 1560 1568 public Font deriveFont(int style, float size){ 1569 Hashtable newAttributes = (Hashtable )getRequestedAttributes().clone(); 1570 applyStyle(style, newAttributes); 1571 applySize(size, newAttributes); 1572 return new Font (newAttributes, createdFont, font2DHandle); 1573 } 1574 1575 1586 public Font deriveFont(int style, AffineTransform trans){ 1587 Hashtable newAttributes = (Hashtable )getRequestedAttributes().clone(); 1588 applyStyle(style, newAttributes); 1589 applyTransform(trans, newAttributes); 1590 return new Font (newAttributes, createdFont, font2DHandle); 1591 } 1592 1593 1600 public Font deriveFont(float size){ 1601 Hashtable newAttributes = (Hashtable )getRequestedAttributes().clone(); 1602 applySize(size, newAttributes); 1603 return new Font (newAttributes, createdFont, font2DHandle); 1604 } 1605 1606 1616 public Font deriveFont(AffineTransform trans){ 1617 Hashtable newAttributes = (Hashtable )getRequestedAttributes().clone(); 1618 applyTransform(trans, newAttributes); 1619 return new Font (newAttributes, createdFont, font2DHandle); 1620 } 1621 1622 1629 public Font deriveFont(int style){ 1630 Hashtable newAttributes = (Hashtable )getRequestedAttributes().clone(); 1631 applyStyle(style, newAttributes); 1632 return new Font (newAttributes, createdFont, font2DHandle); 1633 } 1634 1635 1644 public Font deriveFont(Map <? extends Attribute , ?> attributes) { 1645 if (attributes == null || attributes.size() == 0) { 1646 return this; 1647 } 1648 1649 Hashtable newAttrs = new Hashtable (getAttributes()); 1650 Attribute validAttribs[] = getAvailableAttributes(); 1651 Object obj; 1652 1653 for(int i = 0; i < validAttribs.length; i++){ 1654 if ((obj = attributes.get(validAttribs[i])) != null) { 1655 newAttrs.put(validAttribs[i],obj); 1656 } 1657 } 1658 return new Font (newAttrs, createdFont, font2DHandle); 1659 } 1660 1661 1676 public boolean canDisplay(char c){ 1677 return getFont2D().canDisplay(c); 1678 } 1679 1680 1693 public boolean canDisplay(int codePoint) { 1694 if (!Character.isValidCodePoint(codePoint)) { 1695 throw new IllegalArgumentException ("invalid code point: " + Integer.toHexString(codePoint)); 1696 } 1697 return getFont2D().canDisplay(codePoint); 1698 } 1699 1700 1717 public int canDisplayUpTo(String str) { 1718 return canDisplayUpTo(new StringCharacterIterator (str), 0, 1719 str.length()); 1720 } 1721 1722 1741 public int canDisplayUpTo(char[] text, int start, int limit) { 1742 while (start < limit && canDisplay(text[start])) { 1743 ++start; 1744 } 1745 1746 return start == limit ? -1 : start; 1747 } 1748 1749 1766 public int canDisplayUpTo(CharacterIterator iter, int start, int limit) { 1767 for (char c = iter.setIndex(start); 1768 iter.getIndex() < limit && canDisplay(c); 1769 c = iter.next()) { 1770 } 1771 1772 int result = iter.getIndex(); 1773 return result == limit ? -1 : result; 1774 } 1775 1776 1783 public float getItalicAngle() { 1784 AffineTransform at = (isTransformed()) ? getTransform() : identityTx; 1785 return getFont2D().getItalicAngle(this, at, false, false); 1786 } 1787 1788 1799 public boolean hasUniformLineMetrics() { 1800 return false; } 1802 1803 private transient SoftReference flmref; 1804 private FontLineMetrics defaultLineMetrics(FontRenderContext frc) { 1805 FontLineMetrics flm = null; 1806 if (flmref == null 1807 || (flm = (FontLineMetrics)flmref.get()) == null 1808 || !flm.frc.equals(frc)) { 1809 1810 1815 float [] metrics = new float[4]; 1816 getFont2D().getFontMetrics(this, identityTx, 1817 frc.isAntiAliased(), 1818 frc.usesFractionalMetrics(), 1819 metrics); 1820 float ascent = metrics[0]; 1821 float descent = metrics[1]; 1822 float leading = metrics[2]; 1823 float ssOffset = 0; 1824 if (superscript != 0) { 1825 ssOffset = (float)getTransform().getTranslateY(); 1826 ascent -= ssOffset; 1827 descent += ssOffset; 1828 } 1829 float height = ascent + descent + leading; 1830 1831 int baselineIndex = 0; float[] baselineOffsets = { 0, (descent/2f - ascent) / 2f, -ascent }; 1834 float strikethroughOffset = ssOffset -(metrics[0] / 2.5f); 1836 float strikethroughThickness = (float)(Math.log(pointSize / 4)); 1837 1838 float underlineOffset = ssOffset + strikethroughThickness / 1.5f; 1839 float underlineThickness = strikethroughThickness; 1840 1841 float italicAngle = getItalicAngle(); 1842 1843 CoreMetrics cm = new CoreMetrics(ascent, descent, leading, height, 1844 baselineIndex, baselineOffsets, 1845 strikethroughOffset, strikethroughThickness, 1846 underlineOffset, underlineThickness, 1847 ssOffset, italicAngle); 1848 1849 flm = new FontLineMetrics(0, cm, frc); 1850 flmref = new SoftReference (flm); 1851 } 1852 1853 return (FontLineMetrics)flm.clone(); 1854 } 1855 1856 1864 public LineMetrics getLineMetrics( String str, FontRenderContext frc) { 1865 FontLineMetrics flm = defaultLineMetrics(frc); 1866 flm.numchars = str.length(); 1867 return flm; 1868 } 1869 1870 1880 public LineMetrics getLineMetrics( String str, 1881 int beginIndex, int limit, 1882 FontRenderContext frc) { 1883 FontLineMetrics flm = defaultLineMetrics(frc); 1884 int numChars = limit - beginIndex; 1885 flm.numchars = (numChars < 0)? 0: numChars; 1886 return flm; 1887 } 1888 1889 1899 public LineMetrics getLineMetrics(char [] chars, 1900 int beginIndex, int limit, 1901 FontRenderContext frc) { 1902 FontLineMetrics flm = defaultLineMetrics(frc); 1903 int numChars = limit - beginIndex; 1904 flm.numchars = (numChars < 0)? 0: numChars; 1905 return flm; 1906 } 1907 1908 1918 public LineMetrics getLineMetrics(CharacterIterator ci, 1919 int beginIndex, int limit, 1920 FontRenderContext frc) { 1921 FontLineMetrics flm = defaultLineMetrics(frc); 1922 int numChars = limit - beginIndex; 1923 flm.numchars = (numChars < 0)? 0: numChars; 1924 return flm; 1925 } 1926 1927 1946 public Rectangle2D getStringBounds( String str, FontRenderContext frc) { 1947 char[] array = str.toCharArray(); 1948 return getStringBounds(array, 0, array.length, frc); 1949 } 1950 1951 1976 public Rectangle2D getStringBounds( String str, 1977 int beginIndex, int limit, 1978 FontRenderContext frc) { 1979 String substr = str.substring(beginIndex, limit); 1980 return getStringBounds(substr, frc); 1981 } 1982 1983 2009 public Rectangle2D getStringBounds(char [] chars, 2010 int beginIndex, int limit, 2011 FontRenderContext frc) { 2012 if (beginIndex < 0) { 2013 throw new IndexOutOfBoundsException ("beginIndex: " + beginIndex); 2014 } 2015 if (limit > chars.length) { 2016 throw new IndexOutOfBoundsException ("limit: " + limit); 2017 } 2018 if (beginIndex > limit) { 2019 throw new IndexOutOfBoundsException ("range length: " + (limit - beginIndex)); 2020 } 2021 2022 2025 boolean simple = true; 2026 for (int i = beginIndex; i < limit; ++i) { 2027 char c = chars[i]; 2028 if (c >= '\u0590' && c <= '\u206f') { 2029 simple = false; 2030 break; 2031 } 2032 } 2033 if (simple) { 2034 GlyphVector gv = new StandardGlyphVector(this, chars, beginIndex, limit - beginIndex, frc); 2035 return gv.getLogicalBounds(); 2036 } else { 2037 String str = new String (chars, beginIndex, limit - beginIndex); 2039 TextLayout tl = new TextLayout (str, this, frc); 2040 return new Rectangle2D.Float (0, -tl.getAscent(), tl.getAdvance(), tl.getDescent() + tl.getLeading()); 2041 } 2042 } 2043 2044 2071 public Rectangle2D getStringBounds(CharacterIterator ci, 2072 int beginIndex, int limit, 2073 FontRenderContext frc) { 2074 int start = ci.getBeginIndex(); 2075 int end = ci.getEndIndex(); 2076 2077 if (beginIndex < start) { 2078 throw new IndexOutOfBoundsException ("beginIndex: " + beginIndex); 2079 } 2080 if (limit > end) { 2081 throw new IndexOutOfBoundsException ("limit: " + limit); 2082 } 2083 if (beginIndex > limit) { 2084 throw new IndexOutOfBoundsException ("range length: " + (limit - beginIndex)); 2085 } 2086 2087 char[] arr = new char[limit - beginIndex]; 2088 2089 ci.setIndex(beginIndex); 2090 for(int idx = 0; idx < arr.length; idx++) { 2091 arr[idx] = ci.current(); 2092 ci.next(); 2093 } 2094 2095 return getStringBounds(arr,0,arr.length,frc); 2096 } 2097 2098 2105 public Rectangle2D getMaxCharBounds(FontRenderContext frc) { 2106 float [] metrics = new float[4]; 2107 2108 getFont2D().getFontMetrics(this, frc, metrics); 2109 2110 return new Rectangle2D.Float (0, -metrics[0], 2111 metrics[3], 2112 metrics[0] + metrics[1] + metrics[2]); 2113 } 2114 2115 2129 public GlyphVector createGlyphVector(FontRenderContext frc, String str) 2130 { 2131 return (GlyphVector )new StandardGlyphVector(this, str, frc); 2132 } 2133 2134 2148 public GlyphVector createGlyphVector(FontRenderContext frc, char[] chars) 2149 { 2150 return (GlyphVector )new StandardGlyphVector(this, chars, frc); 2151 } 2152 2153 2167 public GlyphVector createGlyphVector( FontRenderContext frc, 2168 CharacterIterator ci) 2169 { 2170 return (GlyphVector )new StandardGlyphVector(this, ci, frc); 2171 } 2172 2173 2187 public GlyphVector createGlyphVector( FontRenderContext frc, 2188 int [] glyphCodes) 2189 { 2190 return (GlyphVector )new StandardGlyphVector(this, glyphCodes, frc); 2191 } 2192 2193 2234 public GlyphVector layoutGlyphVector(FontRenderContext frc, 2235 char[] text, 2236 int start, 2237 int limit, 2238 int flags) { 2239 2240 GlyphLayout gl = GlyphLayout.get(null); StandardGlyphVector gv = gl.layout(this, frc, text, 2242 start, limit, flags, null); 2243 GlyphLayout.done(gl); 2244 return gv; 2245 } 2246 2247 2251 public static final int LAYOUT_LEFT_TO_RIGHT = 0; 2252 2253 2257 public static final int LAYOUT_RIGHT_TO_LEFT = 1; 2258 2259 2263 public static final int LAYOUT_NO_START_CONTEXT = 2; 2264 2265 2269 public static final int LAYOUT_NO_LIMIT_CONTEXT = 4; 2270 2271 2272 private static void applyTransform(AffineTransform trans, Map attributes) { 2273 if (trans == null) { 2274 throw new IllegalArgumentException ("transform must not be null"); 2275 } 2276 if (trans.isIdentity()) { 2277 attributes.remove(TextAttribute.TRANSFORM); 2278 } else { 2279 attributes.put(TextAttribute.TRANSFORM, new TransformAttribute (trans)); 2280 } 2281 } 2282 2283 private static void applyStyle(int style, Map attributes) { 2284 if ((style & BOLD) != 0) { 2285 attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD); 2286 } else { 2287 attributes.remove(TextAttribute.WEIGHT); 2288 } 2289 2290 if ((style & ITALIC) != 0) { 2291 attributes.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE); 2292 } else { 2293 attributes.remove(TextAttribute.POSTURE); 2294 } 2295 } 2296 2297 private static void applySize(float size, Map attributes) { 2298 attributes.put(TextAttribute.SIZE, new Float (size)); 2299 } 2300 2301 2304 private static native void initIDs(); 2305 private native void pDispose(); 2306 2307 2310 protected void finalize() throws Throwable { 2311 if (this.peer != null) { 2312 pDispose(); 2313 } 2314 super.finalize(); 2315 } 2316} 2317 | Popular Tags |