Frames | No Frames |
1: /* OpenTypeFont.java -- Manages OpenType and TrueType fonts. 2: Copyright (C) 2006 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package gnu.java.awt.font.opentype; 39: 40: import java.awt.Font; 41: import java.awt.FontFormatException; 42: import java.awt.font.FontRenderContext; 43: import java.awt.font.GlyphVector; 44: import java.awt.font.OpenType; 45: import java.awt.geom.AffineTransform; 46: import java.awt.geom.GeneralPath; 47: import java.awt.geom.Point2D; 48: import java.nio.ByteBuffer; 49: import java.text.CharacterIterator; 50: import java.util.Locale; 51: 52: import gnu.java.awt.font.FontDelegate; 53: import gnu.java.awt.font.GNUGlyphVector; 54: import gnu.java.awt.font.opentype.truetype.TrueTypeScaler; 55: 56: 57: /** 58: * A font that takes its data from OpenType or TrueType font tables. 59: * 60: * <p>OpenType is an extension of the TrueType font format. In addition 61: * to tables for names, kerning or layout, it also stores the shapes 62: * of individual glyphs. Three formats are recognized for glyphs: 63: * Quadratic splines (classic TrueType), cubic splines (PostScript), 64: * and bitmaps. 65: * 66: * @see <a 67: * href="http://partners.adobe.com/asn/tech/type/opentype/">Adobe’s 68: * OpenType specification</a> 69: * 70: * @see <a 71: * href="http://developer.apple.com/fonts/TTRefMan/">Apple’s</code> 72: * TrueType specification</a> 73: * 74: * @author Sascha Brawer (brawer@dandelis.ch) 75: */ 76: public final class OpenTypeFont 77: implements FontDelegate 78: { 79: static final int TAG_OTTO = 0x4f54544f; // 'OTTO' 80: static final int TAG_SFNT = 0x73666e74; // 'sfnt' 81: static final int TAG_TRUE = 0x74727565; // 'true' 82: static final int TAG_TTCF = 0x74746366; // 'ttcf' 83: static final int TAG_ZAPF = 0x5a617066; // 'Zapf' 84: 85: 86: /** 87: * A buffer containing the font data. Note that this may well be an 88: * instance of the subclass MappedByteBuffer, in which case the 89: * virtual memory subsystem can more efficiently handle requests for 90: * font data. This is especially recommended for large font files 91: * that contain many glyphs that are rarely accessed. 92: */ 93: ByteBuffer buf; 94: 95: 96: /** 97: * The number of glyphs in this font. 98: */ 99: final int numGlyphs; 100: 101: int[] tableTag, tableStart, tableLength; 102: 103: 104: /** 105: * The version of the font in 16.16 fixed-point encoding, for 106: * example 0x00010000 for version 1.0. There are also two special 107: * version IDs used by fonts for Apple Macintosh, namely 'true' 108: * (0x74727565) and 'typ1'. OpenType fonts sometimes have 'OTTO' as 109: * their version. 110: */ 111: private int version; 112: 113: 114: /** 115: * The number of font units per em. For fonts with TrueType 116: * outlines, this is usually a power of two (such as 2048). For 117: * OpenType fonts with PostScript outlines, other values are 118: * acceptable (such as 1000). 119: */ 120: private int unitsPerEm; 121: 122: 123: /** 124: * A factor to convert font units into ems. This value is <code>1 / 125: * unitsPerEm</code>. 126: */ 127: private float emsPerUnit; 128: 129: 130: /** 131: * The scaler to which the actual scaling work is delegated. 132: */ 133: private Scaler scaler; 134: 135: 136: /** 137: * A delegate object for mapping Unicode UCS-4 codepoints to glyph 138: * IDs. 139: */ 140: private CharGlyphMap cmap; 141: 142: 143: /** 144: * A delegate object for providing a name for each glyph. 145: */ 146: private GlyphNamer glyphNamer; 147: 148: 149: /** 150: * Constructs an OpenType or TrueType font. 151: * 152: * @param buf a buffer with the contents of the font file. It is 153: * recommended to use a <code>MappedByteBuffer</code> for very 154: * large font files. 155: * 156: * @param offsetTablePosition the position of the OpenType offset 157: * table in the font file. The offset table of most OpenType and 158: * TrueType fonts starts at position 0. However, so-called TrueType 159: * Collections support multiple OpenType fonts in a single file, 160: * which allows sharing some glyphs between fonts. If many glyphs 161: * are shared (for example all the Kanji glyphs between multiple 162: * Japanese fonts), the space savings can be considerable. In that 163: * case, the offset table of each individual font would start at its 164: * own position. 165: * 166: * @throws java.awt.FontFormatException if the font data is 167: * not in OpenType or TrueType format. 168: */ 169: OpenTypeFont(ByteBuffer buf, int offsetTablePosition) 170: throws FontFormatException 171: { 172: int numTables, searchRange, entrySelector, rangeShift; 173: 174: //buf = buf.duplicate(); 175: this.buf = buf; 176: buf.limit(buf.capacity()); 177: buf.position(offsetTablePosition); 178: 179: /* Check that the font data is in a supported format. */ 180: version = buf.getInt(); 181: switch (version) 182: { 183: case 0x00010000: // Microsoft TrueType 184: case OpenType.TAG_TYP1: // Adobe PostScript embeded in Apple SFNT ('typ1') 185: case TAG_SFNT: // Apple TrueType 186: case TAG_TRUE: // Apple TrueType 187: case TAG_OTTO: // OpenType 188: break; 189: 190: default: 191: throw new FontFormatException("not in OpenType or TrueType format"); 192: } 193: 194: numTables = buf.getShort(); 195: searchRange = buf.getShort(); 196: entrySelector = buf.getShort(); 197: rangeShift = buf.getShort(); 198: 199: tableTag = new int[numTables]; 200: tableStart = new int[numTables]; 201: tableLength = new int[numTables]; 202: int lastTag = 0; 203: for (int i = 0; i < numTables; i++) 204: { 205: tableTag[i] = buf.getInt(); 206: if (lastTag >= tableTag[i]) 207: throw new FontFormatException("unordered OpenType table"); 208: 209: buf.getInt(); // ignore checksum 210: tableStart[i] = buf.getInt(); 211: tableLength[i] = buf.getInt(); 212: 213: //System.out.println(tagToString(tableTag[i]) + ", " + tableLength[i]); 214: } 215: 216: ByteBuffer head = getFontTable(OpenType.TAG_HEAD); 217: if ((head.getInt(0) != 0x00010000) 218: || (head.getInt(12) != 0x5f0f3cf5)) 219: throw new FontFormatException("unsupported head version"); 220: 221: unitsPerEm = head.getChar(18); 222: emsPerUnit = 1.0f / (float) unitsPerEm; 223: 224: 225: ByteBuffer maxp = getFontTable(OpenType.TAG_MAXP); 226: int maxpVersion = maxp.getInt(0); 227: switch (maxpVersion) 228: { 229: case 0x00005000: /* version 0.5, with wrong fractional part */ 230: numGlyphs = maxp.getChar(4); 231: break; 232: 233: case 0x00010000: /* version 1.0 */ 234: numGlyphs = maxp.getChar(4); 235: scaler = new TrueTypeScaler(unitsPerEm, 236: getFontTable(OpenType.TAG_HHEA), 237: getFontTable(OpenType.TAG_HMTX), 238: getFontTable(OpenType.TAG_VHEA), 239: getFontTable(OpenType.TAG_VMTX), 240: maxp, 241: getFontTable(OpenType.TAG_CVT), 242: getFontTable(OpenType.TAG_FPGM), 243: /* loca format */ head.getShort(50), 244: getFontTable(OpenType.TAG_LOCA), 245: getFontTable(OpenType.TAG_GLYF), 246: getFontTable(OpenType.TAG_PREP)); 247: break; 248: 249: default: 250: throw new FontFormatException("unsupported maxp version"); 251: } 252: } 253: 254: 255: /** 256: * Determines the index of a table into the offset table. The 257: * result can be used to find the offset and length of a table, as 258: * in <code>tableStart[getTableIndex(TAG_NAME)]</code>. 259: * 260: * @param tag the table identifier, for instance 261: * <code>OpenType.TAG_NAME</code>. 262: * 263: * @return the index of that table into the offset table, or 264: * -1 if the font does not contain the table specified by 265: * <code>tag</code>. 266: */ 267: private int getTableIndex(int tag) 268: { 269: /* FIXME: Since the font specification requires tableTag[] to be 270: * ordered, one should do binary search here. 271: */ 272: for (int i = 0; i < tableTag.length; i++) 273: if (tableTag[i] == tag) 274: return i; 275: return -1; 276: } 277: 278: 279: 280: /** 281: * Returns the name of the family to which this font face belongs, 282: * for example <i>“Univers”</i>. 283: * 284: * @param locale the locale for which to localize the name. 285: * 286: * @return the family name. 287: */ 288: public synchronized String getFamilyName(Locale locale) 289: { 290: String name; 291: 292: if (locale == null) 293: locale = Locale.getDefault(); 294: 295: name = getName(NameDecoder.NAME_FAMILY, locale); 296: if (name == null) 297: name = getName(NameDecoder.NAME_FAMILY, Locale.ENGLISH); 298: if (name == null) 299: name = getName(NameDecoder.NAME_FAMILY, /* any language */ null); 300: if (name == null) 301: name = getName(NameDecoder.NAME_FULL, locale); 302: if (name == null) 303: name = getName(NameDecoder.NAME_FULL, /* any language */ null); 304: return name; 305: } 306: 307: 308: /** 309: * Returns the name of this font face inside the family, for example 310: * <i>“Light”</i>. 311: * 312: * @param locale the locale for which to localize the name. 313: * 314: * @return the name of the face inside its family. 315: */ 316: public synchronized String getSubFamilyName(Locale locale) 317: { 318: String name; 319: 320: if (locale == null) 321: locale = Locale.getDefault(); 322: 323: name = getName(NameDecoder.NAME_SUBFAMILY, locale); 324: if (name == null) 325: { 326: name = getName(NameDecoder.NAME_SUBFAMILY, Locale.ENGLISH); 327: if ("Regular".equals(name)) 328: name = null; 329: } 330: 331: if (name == null) 332: { 333: String lang = locale.getLanguage(); 334: if ("de".equals(lang)) 335: name = "Standard"; 336: else if ("fr".equals(lang)) 337: name = "Standard"; 338: else if ("it".equals(lang)) 339: name = "Normale"; 340: else if ("nl".equals(lang)) 341: name = "Normaal"; 342: else if ("fi".equals(lang)) 343: name = "Normaali"; 344: else if ("sv".equals(lang)) 345: name = "Normal"; 346: else 347: name = "Regular"; 348: } 349: 350: return name; 351: } 352: 353: 354: 355: /** 356: * Returns the full name of this font face, for example 357: * <i>“Univers Light”</i>. 358: * 359: * @param locale the locale for which to localize the name. 360: * 361: * @return the face name. 362: */ 363: public synchronized String getFullName(Locale locale) 364: { 365: String name; 366: 367: if (locale == null) 368: locale = Locale.getDefault(); 369: 370: name = getName(NameDecoder.NAME_FULL, locale); 371: if (name == null) 372: name = getName(NameDecoder.NAME_FULL, Locale.ENGLISH); 373: if (name == null) 374: name = getName(NameDecoder.NAME_FULL, /* any language */ null); 375: 376: return name; 377: } 378: 379: 380: /** 381: * Returns the PostScript name of this font face, for example 382: * <i>“Univers-Light”</i>. 383: * 384: * @return the PostScript name, or <code>null</code> if the font 385: * does not provide a PostScript name. 386: */ 387: public synchronized String getPostScriptName() 388: { 389: return getName(NameDecoder.NAME_POSTSCRIPT, /* any language */ null); 390: } 391: 392: 393: /** 394: * Returns the number of glyphs in this font face. 395: */ 396: public int getNumGlyphs() 397: { 398: /* No synchronization is needed because the number of glyphs is 399: * set in the constructor, and it cannot change during the 400: * lifetime of the object. 401: */ 402: return numGlyphs; 403: } 404: 405: 406: /** 407: * Returns the index of the glyph which gets displayed if the font 408: * cannot map a Unicode code point to a glyph. Many fonts show this 409: * glyph as an empty box. 410: */ 411: public int getMissingGlyphCode() 412: { 413: /* No synchronization is needed because the result is constant. */ 414: return 0; 415: } 416: 417: 418: /** 419: * The font’s name table, or <code>null</code> if this 420: * table has not yet been accessed. 421: */ 422: private ByteBuffer nameTable; 423: 424: 425: /** 426: * Extracts a String from the font’s name table. 427: * 428: * @param name the numeric TrueType or OpenType name ID. 429: * 430: * @param locale the locale for which names shall be localized, or 431: * <code>null</code> if the locale does mot matter because the name 432: * is known to be language-independent (for example, because it is 433: * the PostScript name). 434: */ 435: private String getName(int name, Locale locale) 436: { 437: if (nameTable == null) 438: nameTable = getFontTable(OpenType.TAG_NAME); 439: return NameDecoder.getName(nameTable, name, locale); 440: } 441: 442: 443: /** 444: * Returns the version of the font. 445: * 446: * @see java.awt.font.OpenType#getVersion 447: * 448: * @return the version in 16.16 fixed-point encoding, for example 449: * 0x00010000 for version 1.0. 450: */ 451: public int getVersion() 452: { 453: /* No synchronization is needed because the version is set in the 454: * constructor, and it cannot change during the lifetime of the 455: * object. 456: */ 457: return version; 458: } 459: 460: 461: /** 462: * Creates a view buffer for an OpenType table. The caller can 463: * access the returned buffer without needing to synchronize access 464: * from multiple threads. 465: * 466: * @param tag the table identifier, for example 467: * <code>OpenType.GLYF</code>. 468: * 469: * @return a slice of the underlying buffer containing the table, or 470: * <code>null</code> if the font does not contain the requested 471: * table. 472: */ 473: public synchronized ByteBuffer getFontTable(int tag) 474: { 475: int index, start, len; 476: ByteBuffer result; 477: 478: index = getTableIndex(tag); 479: if (index < 0) 480: return null; 481: 482: start = tableStart[index]; 483: len = tableLength[index]; 484: buf.limit(start + len).position(start); 485: result = buf.slice(); 486: result.limit(len); 487: return result; 488: } 489: 490: 491: /** 492: * Returns the size of one of the tables in the font, 493: * or -1 if the table does not exist. 494: */ 495: public int getFontTableSize(int tag) 496: { 497: int index = getTableIndex(tag); 498: if (index == -1) 499: return index; 500: return tableLength[index]; 501: } 502: 503: 504: private CharGlyphMap getCharGlyphMap() 505: { 506: if (cmap != null) 507: return cmap; 508: 509: synchronized (this) 510: { 511: if (cmap == null) 512: { 513: int index = getTableIndex(OpenType.TAG_CMAP); 514: int start = tableStart[index]; 515: buf.limit(start + tableLength[index]).position(start); 516: cmap = CharGlyphMap.forTable(buf); 517: } 518: return cmap; 519: } 520: } 521: 522: 523: 524: /** 525: * Looks up a glyph in the font’s <code>cmap</code> tables, 526: * without performing any glyph substitution or reordering. Because 527: * of this limitation, this method cannot be used for script systems 528: * that need advanced glyph mapping, such as Arabic, Korean, or even 529: * Latin with exotic accents. 530: * 531: * <p>It is safe to call this method from any thread. 532: * 533: * @param ucs4 the Unicode codepoint in the 32-bit Unicode character 534: * set UCS-4. Because UTF-16 surrogates do not correspond to a single 535: * glyph, it does not make sense to pass them here. 536: * 537: * @return the glyph index, or zero if the font does not contain 538: * a glyph for the specified codepoint. 539: */ 540: public int getGlyph(int ucs4) 541: { 542: return getCharGlyphMap().getGlyph(ucs4); 543: } 544: 545: 546: /** 547: * Creates a GlyphVector by mapping each character in a 548: * CharacterIterator to the corresponding glyph. 549: * 550: * <p>The mapping takes only the font’s <code>cmap</code> 551: * tables into consideration. No other operations (such as glyph 552: * re-ordering, composition, or ligature substitution) are 553: * performed. This means that the resulting GlyphVector will not be 554: * correct for text in languages that have complex 555: * character-to-glyph mappings, such as Arabic, Hebrew, Hindi, or 556: * Thai. 557: * 558: * @param font the font object that the created GlyphVector 559: * will return when it gets asked for its font. This argument is 560: * needed because the public API works with java.awt.Font, 561: * not with some private delegate like OpenTypeFont. 562: * 563: * @param frc the font rendering parameters that are used for 564: * measuring glyphs. The exact placement of text slightly depends on 565: * device-specific characteristics, for instance the device 566: * resolution or anti-aliasing. For this reason, any measurements 567: * will only be accurate if the passed 568: * <code>FontRenderContext</code> correctly reflects the relevant 569: * parameters. Hence, <code>frc</code> should be obtained from the 570: * same <code>Graphics2D</code> that will be used for drawing, and 571: * any rendering hints should be set to the desired values before 572: * obtaining <code>frc</code>. 573: * 574: * @param ci a CharacterIterator for iterating over the 575: * characters to be displayed. 576: */ 577: public synchronized GlyphVector createGlyphVector(Font font, 578: FontRenderContext frc, 579: CharacterIterator ci) 580: { 581: CharGlyphMap cmap; 582: int numGlyphs; 583: int[] glyphs; 584: int glyph; 585: int c; 586: 587: cmap = getCharGlyphMap(); 588: numGlyphs = ci.getEndIndex() - ci.getBeginIndex(); 589: glyphs = new int[numGlyphs]; 590: glyph = 0; 591: for (c = ci.first(); c != CharacterIterator.DONE; c = ci.next()) 592: { 593: /* handle surrogate pairs */ 594: if (c >> 10 == 0x36) // U+D800 .. U+DBFF: High surrogate 595: c = (((c & 0x3ff) << 10) | (ci.next() & 0x3ff)) + 0x10000; 596: glyphs[glyph] = cmap.getGlyph(c); 597: glyph += 1; 598: } 599: 600: /* If we had surrogates, the allocated array is too large. 601: * Because this will occur very rarely, it seems acceptable to 602: * re-allocate a shorter array and copy the contents around. 603: */ 604: if (glyph != numGlyphs) 605: { 606: int[] newGlyphs = new int[glyph]; 607: System.arraycopy(glyphs, 0, newGlyphs, 0, glyph); 608: glyphs = newGlyphs; 609: } 610: 611: return new GNUGlyphVector(this, font, frc, glyphs); 612: } 613: 614: 615: 616: /** 617: * Determines the advance width for a glyph. 618: * 619: * @param glyphIndex the glyph whose advance width is to be 620: * determined. 621: * 622: * @param pointSize the point size of the font. 623: * 624: * @param transform a transform that is applied in addition to 625: * scaling to the specified point size. This is often used for 626: * scaling according to the device resolution. Those who lack any 627: * aesthetic sense may also use the transform to slant or stretch 628: * glyphs. 629: * 630: * @param antialias <code>true</code> for anti-aliased rendering, 631: * <code>false</code> for normal rendering. For hinted fonts, 632: * this parameter may indeed affect the result. 633: * 634: * @param fractionalMetrics <code>true</code> for fractional metrics, 635: * <code>false</code> for rounding the result to a pixel boundary. 636: * 637: * @param horizontal <code>true</code> for horizontal line layout, 638: * <code>false</code> for vertical line layout. 639: * 640: * @param advance a point whose <code>x</code> and <code>y</code> 641: * fields will hold the advance in each direction. It is possible 642: * that both values are non-zero, for example if 643: * <code>transform</code> is a rotation, or in the case of Urdu 644: * fonts. 645: */ 646: public synchronized void getAdvance(int glyphIndex, 647: float pointSize, 648: AffineTransform transform, 649: boolean antialias, 650: boolean fractionalMetrics, 651: boolean horizontal, 652: Point2D advance) 653: { 654: /* Delegate the measurement to the scaler. The synchronization is 655: * needed because the scaler is not synchronized. 656: */ 657: scaler.getAdvance(glyphIndex, pointSize, transform, 658: antialias, fractionalMetrics, horizontal, 659: advance); 660: } 661: 662: 663: /** 664: * Returns the shape of a glyph. 665: * 666: * @param glyph the glyph whose advance width is to be determined 667: * 668: * @param pointSize the point size of the font. 669: * 670: * @param transform a transform that is applied in addition to 671: * scaling to the specified point size. This is often used for 672: * scaling according to the device resolution. Those who lack any 673: * aesthetic sense may also use the transform to slant or stretch 674: * glyphs. 675: * 676: * @param antialias <code>true</code> for anti-aliased rendering, 677: * <code>false</code> for normal rendering. For hinted fonts, this 678: * parameter may indeed affect the result. 679: * 680: * @param fractionalMetrics <code>true</code> for fractional 681: * metrics, <code>false</code> for rounding the result to a pixel 682: * boundary. 683: * 684: * @return the scaled and grid-fitted outline of the specified 685: * glyph, or <code>null</code> for bitmap fonts. 686: */ 687: public synchronized GeneralPath getGlyphOutline(int glyph, 688: float pointSize, 689: AffineTransform transform, 690: boolean antialias, 691: boolean fractionalMetrics) 692: { 693: /* The synchronization is needed because the scaler is not 694: * synchronized. 695: */ 696: return scaler.getOutline(glyph, pointSize, transform, 697: antialias, fractionalMetrics); 698: } 699: 700: 701: /** 702: * Returns a name for the specified glyph. This is useful for 703: * generating PostScript or PDF files that embed some glyphs of a 704: * font. 705: * 706: * <p><b>Names are not unique:</b> Under some rare circumstances, 707: * the same name can be returned for different glyphs. It is 708: * therefore recommended that printer drivers check whether the same 709: * name has already been returned for antoher glyph, and make the 710: * name unique by adding the string ".alt" followed by the glyph 711: * index.</p> 712: * 713: * <p>This situation would occur for an OpenType or TrueType font 714: * that has a <code>post</code> table of format 3 and provides a 715: * mapping from glyph IDs to Unicode sequences through a 716: * <code>Zapf</code> table. If the same sequence of Unicode 717: * codepoints leads to different glyphs (depending on contextual 718: * position, for example, or on typographic sophistication level), 719: * the same name would get synthesized for those glyphs. 720: * 721: * @param glyphIndex the glyph whose name the caller wants to 722: * retrieve. 723: */ 724: public synchronized String getGlyphName(int glyphIndex) 725: { 726: if (glyphNamer == null) 727: glyphNamer = GlyphNamer.forTables(numGlyphs, 728: getFontTable(OpenType.TAG_POST), 729: getFontTable(TAG_ZAPF)); 730: 731: return glyphNamer.getGlyphName(glyphIndex); 732: } 733: 734: 735: /** 736: * Determines the distance between the base line and the highest 737: * ascender. 738: * 739: * @param pointSize the point size of the font. 740: * 741: * @param transform a transform that is applied in addition to 742: * scaling to the specified point size. This is often used for 743: * scaling according to the device resolution. Those who lack any 744: * aesthetic sense may also use the transform to slant or stretch 745: * glyphs. 746: * 747: * @param antialiased <code>true</code> for anti-aliased rendering, 748: * <code>false</code> for normal rendering. For hinted fonts, 749: * this parameter may indeed affect the result. 750: * 751: * @param fractionalMetrics <code>true</code> for fractional metrics, 752: * <code>false</code> for rounding the result to a pixel boundary. 753: * 754: * @param horizontal <code>true</code> for horizontal line layout, 755: * <code>false</code> for vertical line layout. 756: * 757: * @return the ascent, which usually is a positive number. 758: */ 759: public synchronized float getAscent(float pointSize, 760: AffineTransform transform, 761: boolean antialiased, 762: boolean fractionalMetrics, 763: boolean horizontal) 764: { 765: return scaler.getAscent(pointSize, transform, 766: antialiased, fractionalMetrics, 767: horizontal); 768: } 769: 770: 771: /** 772: * Determines the distance between the base line and the lowest 773: * descender. 774: * 775: * @param pointSize the point size of the font. 776: * 777: * @param transform a transform that is applied in addition to 778: * scaling to the specified point size. This is often used for 779: * scaling according to the device resolution. Those who lack any 780: * aesthetic sense may also use the transform to slant or stretch 781: * glyphs. 782: * 783: * @param antialiased <code>true</code> for anti-aliased rendering, 784: * <code>false</code> for normal rendering. For hinted fonts, 785: * this parameter may indeed affect the result. 786: * 787: * @param fractionalMetrics <code>true</code> for fractional metrics, 788: * <code>false</code> for rounding the result to a pixel boundary. 789: * 790: * @param horizontal <code>true</code> for horizontal line layout, 791: * <code>false</code> for vertical line layout. 792: * 793: * @return the descent, which usually is a nagative number. 794: */ 795: public synchronized float getDescent(float pointSize, 796: AffineTransform transform, 797: boolean antialiased, 798: boolean fractionalMetrics, 799: boolean horizontal) 800: { 801: return scaler.getDescent(pointSize, transform, 802: antialiased, fractionalMetrics, 803: horizontal); 804: } 805: 806: 807: /** 808: * Converts a four-byte tag identifier into a String that can be 809: * displayed when debugging this class. 810: * 811: * @param tag the tag as an <code>int</code>. 812: * 813: * @return the tag in human-readable form, for example 814: * <code>name</code> or <code>glyf</code>. 815: */ 816: static String tagToString(int tag) 817: { 818: char[] c = new char[4]; 819: c[0] = (char) ((tag >> 24) & 0xff); 820: c[1] = (char) ((tag >> 16) & 0xff); 821: c[2] = (char) ((tag >> 8) & 0xff); 822: c[3] = (char) (tag & 0xff); 823: return new String(c); 824: } 825: }