Merged with mainline at revision 128810.
[official-gcc.git] / libjava / classpath / gnu / java / awt / font / opentype / OpenTypeFont.java
blob6c2193b94ae892ee914870057856a2db8ac86546
1 /* OpenTypeFont.java -- Manages OpenType and TrueType fonts.
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
38 package gnu.java.awt.font.opentype;
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;
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;
59 /**
60 * A font that takes its data from OpenType or TrueType font tables.
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.
68 * @see <a
69 * href="http://partners.adobe.com/asn/tech/type/opentype/">Adobe&#x2019;s
70 * OpenType specification</a>
72 * @see <a
73 * href="http://developer.apple.com/fonts/TTRefMan/">Apple&#x2019;s</code>
74 * TrueType specification</a>
76 * @author Sascha Brawer (brawer@dandelis.ch)
78 public final class OpenTypeFont
79 implements FontDelegate
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'
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.
95 ByteBuffer buf;
98 /**
99 * The number of glyphs in this font.
101 final int numGlyphs;
103 int[] tableTag, tableStart, tableLength;
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.
113 private int version;
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).
122 public int unitsPerEm;
126 * A factor to convert font units into ems. This value is <code>1 /
127 * unitsPerEm</code>.
129 private float emsPerUnit;
133 * The scaler to which the actual scaling work is delegated.
135 private Scaler scaler;
139 * A delegate object for mapping Unicode UCS-4 codepoints to glyph
140 * IDs.
142 private CharGlyphMap cmap;
146 * A delegate object for providing a name for each glyph.
148 private GlyphNamer glyphNamer;
150 private Hinter hinter;
153 * Constructs an OpenType or TrueType font.
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.
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.
169 * @throws java.awt.FontFormatException if the font data is
170 * not in OpenType or TrueType format.
172 OpenTypeFont(ByteBuffer buf, int offsetTablePosition)
173 throws FontFormatException
175 int numTables, searchRange, entrySelector, rangeShift;
177 //buf = buf.duplicate();
178 this.buf = buf;
179 buf.limit(buf.capacity());
180 buf.position(offsetTablePosition);
182 /* Check that the font data is in a supported format. */
183 version = buf.getInt();
184 switch (version)
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;
193 default:
194 throw new FontFormatException("not in OpenType or TrueType format");
197 numTables = buf.getShort();
198 searchRange = buf.getShort();
199 entrySelector = buf.getShort();
200 rangeShift = buf.getShort();
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++)
208 tableTag[i] = buf.getInt();
209 if (lastTag >= tableTag[i])
210 throw new FontFormatException("unordered OpenType table");
212 buf.getInt(); // ignore checksum
213 tableStart[i] = buf.getInt();
214 tableLength[i] = buf.getInt();
216 //System.out.println(tagToString(tableTag[i]) + ", " + tableLength[i]);
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");
224 unitsPerEm = head.getChar(18);
225 emsPerUnit = 1.0f / (float) unitsPerEm;
228 ByteBuffer maxp = getFontTable(OpenType.TAG_MAXP);
229 int maxpVersion = maxp.getInt(0);
230 switch (maxpVersion)
232 case 0x00005000: /* version 0.5, with wrong fractional part */
233 numGlyphs = maxp.getChar(4);
234 break;
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;
252 default:
253 throw new FontFormatException("unsupported maxp version");
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>.
263 * @param tag the table identifier, for instance
264 * <code>OpenType.TAG_NAME</code>.
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>.
270 private int getTableIndex(int tag)
272 /* FIXME: Since the font specification requires tableTag[] to be
273 * ordered, one should do binary search here.
275 for (int i = 0; i < tableTag.length; i++)
276 if (tableTag[i] == tag)
277 return i;
278 return -1;
284 * Returns the name of the family to which this font face belongs,
285 * for example <i>&#x201c;Univers&#x201d;</i>.
287 * @param locale the locale for which to localize the name.
289 * @return the family name.
291 public synchronized String getFamilyName(Locale locale)
293 String name;
295 if (locale == null)
296 locale = Locale.getDefault();
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;
312 * Returns the name of this font face inside the family, for example
313 * <i>&#x201c;Light&#x201d;</i>.
315 * @param locale the locale for which to localize the name.
317 * @return the name of the face inside its family.
319 public synchronized String getSubFamilyName(Locale locale)
321 String name;
323 if (locale == null)
324 locale = Locale.getDefault();
326 name = getName(NameDecoder.NAME_SUBFAMILY, locale);
327 if (name == null)
329 name = getName(NameDecoder.NAME_SUBFAMILY, Locale.ENGLISH);
330 if ("Regular".equals(name))
331 name = null;
334 if (name == null)
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";
353 return name;
359 * Returns the full name of this font face, for example
360 * <i>&#x201c;Univers Light&#x201d;</i>.
362 * @param locale the locale for which to localize the name.
364 * @return the face name.
366 public synchronized String getFullName(Locale locale)
368 String name;
370 if (locale == null)
371 locale = Locale.getDefault();
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);
379 return name;
384 * Returns the PostScript name of this font face, for example
385 * <i>&#x201c;Univers-Light&#x201d;</i>.
387 * @return the PostScript name, or <code>null</code> if the font
388 * does not provide a PostScript name.
390 public synchronized String getPostScriptName()
392 return getName(NameDecoder.NAME_POSTSCRIPT, /* any language */ null);
397 * Returns the number of glyphs in this font face.
399 public int getNumGlyphs()
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.
405 return numGlyphs;
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.
414 public int getMissingGlyphCode()
416 /* No synchronization is needed because the result is constant. */
417 return 0;
422 * The font&#x2019;s name table, or <code>null</code> if this
423 * table has not yet been accessed.
425 private ByteBuffer nameTable;
429 * Extracts a String from the font&#x2019;s name table.
431 * @param name the numeric TrueType or OpenType name ID.
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).
438 private String getName(int name, Locale locale)
440 if (nameTable == null)
441 nameTable = getFontTable(OpenType.TAG_NAME);
442 return NameDecoder.getName(nameTable, name, locale);
447 * Returns the version of the font.
449 * @see java.awt.font.OpenType#getVersion
451 * @return the version in 16.16 fixed-point encoding, for example
452 * 0x00010000 for version 1.0.
454 public int getVersion()
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.
460 return version;
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.
469 * @param tag the table identifier, for example
470 * <code>OpenType.GLYF</code>.
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.
476 public synchronized ByteBuffer getFontTable(int tag)
478 int index, start, len;
479 ByteBuffer result;
481 index = getTableIndex(tag);
482 if (index < 0)
483 return null;
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;
495 * Returns the size of one of the tables in the font,
496 * or -1 if the table does not exist.
498 public int getFontTableSize(int tag)
500 int index = getTableIndex(tag);
501 if (index == -1)
502 return index;
503 return tableLength[index];
507 private CharGlyphMap getCharGlyphMap()
509 if (cmap != null)
510 return cmap;
512 synchronized (this)
514 if (cmap == null)
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);
521 return cmap;
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.
534 * <p>It is safe to call this method from any thread.
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.
540 * @return the glyph index, or zero if the font does not contain
541 * a glyph for the specified codepoint.
543 public int getGlyph(int ucs4)
545 return getCharGlyphMap().getGlyph(ucs4);
550 * Creates a GlyphVector by mapping each character in a
551 * CharacterIterator to the corresponding glyph.
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.
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.
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>.
577 * @param ci a CharacterIterator for iterating over the
578 * characters to be displayed.
580 public synchronized GlyphVector createGlyphVector(Font font,
581 FontRenderContext frc,
582 CharacterIterator ci)
584 // Initialize hinter if necessary.
585 checkHinter(FontDelegate.FLAG_FITTED);
587 CharGlyphMap cmap;
588 int numGlyphs;
589 int[] glyphs;
590 int glyph;
591 int c;
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())
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;
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.
610 if (glyph != numGlyphs)
612 int[] newGlyphs = new int[glyph];
613 System.arraycopy(glyphs, 0, newGlyphs, 0, glyph);
614 glyphs = newGlyphs;
617 return new GNUGlyphVector(this, font, frc, glyphs);
621 * Returns the glyph code for the specified character.
623 * @param c the character to map
625 * @return the glyph code
627 public int getGlyphIndex(int c)
629 return getCharGlyphMap().getGlyph(c);
633 * Determines the advance width for a glyph.
635 * @param glyphIndex the glyph whose advance width is to be
636 * determined.
638 * @param pointSize the point size of the font.
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.
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.
650 * @param fractionalMetrics <code>true</code> for fractional metrics,
651 * <code>false</code> for rounding the result to a pixel boundary.
653 * @param horizontal <code>true</code> for horizontal line layout,
654 * <code>false</code> for vertical line layout.
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.
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)
670 /* Delegate the measurement to the scaler. The synchronization is
671 * needed because the scaler is not synchronized.
673 scaler.getAdvance(glyphIndex, pointSize, transform,
674 antialias, fractionalMetrics, horizontal,
675 advance);
680 * Returns the shape of a glyph.
682 * @param glyph the glyph whose advance width is to be determined
684 * @param pointSize the point size of the font.
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.
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.
696 * @param fractionalMetrics <code>true</code> for fractional
697 * metrics, <code>false</code> for rounding the result to a pixel
698 * boundary.
700 * @return the scaled and grid-fitted outline of the specified
701 * glyph, or <code>null</code> for bitmap fonts.
703 public synchronized GeneralPath getGlyphOutline(int glyph,
704 float pointSize,
705 AffineTransform transform,
706 boolean antialias,
707 boolean fractionalMetrics,
708 int flags)
710 /* The synchronization is needed because the scaler is not
711 * synchronized.
713 checkHinter(flags);
714 return scaler.getOutline(glyph, pointSize, transform,
715 antialias, fractionalMetrics, hinter, flags);
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.
722 * @param glyph the glyph index to fetch
723 * @param transform the transform to apply
725 * @return the raw outline of that glyph
727 public synchronized Zone getRawGlyphOutline(int glyph,
728 AffineTransform transform)
730 return scaler.getRawOutline(glyph, transform);
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.
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>
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.
753 * @param glyphIndex the glyph whose name the caller wants to
754 * retrieve.
756 public synchronized String getGlyphName(int glyphIndex)
758 if (glyphNamer == null)
759 glyphNamer = GlyphNamer.forTables(numGlyphs,
760 getFontTable(OpenType.TAG_POST),
761 getFontTable(TAG_ZAPF));
763 return glyphNamer.getGlyphName(glyphIndex);
768 * Determines the distance between the base line and the highest
769 * ascender.
771 * @param pointSize the point size of the font.
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.
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.
783 * @param fractionalMetrics <code>true</code> for fractional metrics,
784 * <code>false</code> for rounding the result to a pixel boundary.
786 * @param horizontal <code>true</code> for horizontal line layout,
787 * <code>false</code> for vertical line layout.
789 * @return the ascent, which usually is a positive number.
791 public synchronized float getAscent(float pointSize,
792 AffineTransform transform,
793 boolean antialiased,
794 boolean fractionalMetrics,
795 boolean horizontal)
797 return scaler.getAscent(pointSize, transform,
798 antialiased, fractionalMetrics,
799 horizontal);
804 * Determines the distance between the base line and the lowest
805 * descender.
807 * @param pointSize the point size of the font.
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.
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.
819 * @param fractionalMetrics <code>true</code> for fractional metrics,
820 * <code>false</code> for rounding the result to a pixel boundary.
822 * @param horizontal <code>true</code> for horizontal line layout,
823 * <code>false</code> for vertical line layout.
825 * @return the descent, which usually is a nagative number.
827 public synchronized float getDescent(float pointSize,
828 AffineTransform transform,
829 boolean antialiased,
830 boolean fractionalMetrics,
831 boolean horizontal)
833 return scaler.getDescent(pointSize, transform,
834 antialiased, fractionalMetrics,
835 horizontal);
840 * Converts a four-byte tag identifier into a String that can be
841 * displayed when debugging this class.
843 * @param tag the tag as an <code>int</code>.
845 * @return the tag in human-readable form, for example
846 * <code>name</code> or <code>glyf</code>.
848 static String tagToString(int tag)
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);
859 * Checks if a hinter is installed and installs one when not.
861 private void checkHinter(int flags)
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)
870 hinter = new AutoHinter();
871 hinter.init(this);
873 catch (Exception ex)
875 // Protect from problems inside hinter.
876 hinter = null;
877 ex.printStackTrace();
880 hinter.setFlags(flags);