Source for gnu.java.awt.font.opentype.OpenTypeFont

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