OSDN Git Service

Normalise whitespace in GNU Classpath.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / java / awt / font / opentype / OpenTypeFont.java
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 }