OSDN Git Service

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