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)
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
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
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;
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.opentype.truetype.TrueTypeScaler;
55 import gnu.java.awt.font.opentype.truetype.Zone;
59 * A font that takes its data from OpenType or TrueType font tables.
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),
68 * href="http://partners.adobe.com/asn/tech/type/opentype/">Adobe’s
69 * OpenType specification</a>
72 * href="http://developer.apple.com/fonts/TTRefMan/">Apple’s</code>
73 * TrueType specification</a>
75 * @author Sascha Brawer (brawer@dandelis.ch)
77 public final class OpenTypeFont
78 implements FontDelegate
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'
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.
98 * The number of glyphs in this font.
102 int[] tableTag, tableStart, tableLength;
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
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).
121 public int unitsPerEm;
125 * A factor to convert font units into ems. This value is <code>1 /
128 private float emsPerUnit;
132 * The scaler to which the actual scaling work is delegated.
134 private Scaler scaler;
138 * A delegate object for mapping Unicode UCS-4 codepoints to glyph
141 private CharGlyphMap cmap;
145 * A delegate object for providing a name for each glyph.
147 private GlyphNamer glyphNamer;
151 * Constructs an OpenType or TrueType font.
153 * @param buf a buffer with the contents of the font file. It is
154 * recommended to use a <code>MappedByteBuffer</code> for very
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
167 * @throws java.awt.FontFormatException if the font data is
168 * not in OpenType or TrueType format.
170 OpenTypeFont(ByteBuffer buf, int offsetTablePosition)
171 throws FontFormatException
173 int numTables, searchRange, entrySelector, rangeShift;
175 //buf = buf.duplicate();
177 buf.limit(buf.capacity());
178 buf.position(offsetTablePosition);
180 /* Check that the font data is in a supported format. */
181 version = buf.getInt();
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
192 throw new FontFormatException("not in OpenType or TrueType format");
195 numTables = buf.getShort();
196 searchRange = buf.getShort();
197 entrySelector = buf.getShort();
198 rangeShift = buf.getShort();
200 tableTag = new int[numTables];
201 tableStart = new int[numTables];
202 tableLength = new int[numTables];
204 for (int i = 0; i < numTables; i++)
206 tableTag[i] = buf.getInt();
207 if (lastTag >= tableTag[i])
208 throw new FontFormatException("unordered OpenType table");
210 buf.getInt(); // ignore checksum
211 tableStart[i] = buf.getInt();
212 tableLength[i] = buf.getInt();
214 //System.out.println(tagToString(tableTag[i]) + ", " + tableLength[i]);
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");
222 unitsPerEm = head.getChar(18);
223 emsPerUnit = 1.0f / (float) unitsPerEm;
226 ByteBuffer maxp = getFontTable(OpenType.TAG_MAXP);
227 int maxpVersion = maxp.getInt(0);
230 case 0x00005000: /* version 0.5, with wrong fractional part */
231 numGlyphs = maxp.getChar(4);
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),
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));
251 throw new FontFormatException("unsupported maxp version");
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>.
261 * @param tag the table identifier, for instance
262 * <code>OpenType.TAG_NAME</code>.
264 * @return the index of that table into the offset table, or
265 * -1 if the font does not contain the table specified by
268 private int getTableIndex(int tag)
270 /* FIXME: Since the font specification requires tableTag[] to be
271 * ordered, one should do binary search here.
273 for (int i = 0; i < tableTag.length; i++)
274 if (tableTag[i] == tag)
282 * Returns the name of the family to which this font face belongs,
283 * for example <i>“Univers”</i>.
285 * @param locale the locale for which to localize the name.
287 * @return the family name.
289 public synchronized String getFamilyName(Locale locale)
294 locale = Locale.getDefault();
296 name = getName(NameDecoder.NAME_FAMILY, locale);
298 name = getName(NameDecoder.NAME_FAMILY, Locale.ENGLISH);
300 name = getName(NameDecoder.NAME_FAMILY, /* any language */ null);
302 name = getName(NameDecoder.NAME_FULL, locale);
304 name = getName(NameDecoder.NAME_FULL, /* any language */ null);
310 * Returns the name of this font face inside the family, for example
311 * <i>“Light”</i>.
313 * @param locale the locale for which to localize the name.
315 * @return the name of the face inside its family.
317 public synchronized String getSubFamilyName(Locale locale)
322 locale = Locale.getDefault();
324 name = getName(NameDecoder.NAME_SUBFAMILY, locale);
327 name = getName(NameDecoder.NAME_SUBFAMILY, Locale.ENGLISH);
328 if ("Regular".equals(name))
334 String lang = locale.getLanguage();
335 if ("de".equals(lang))
337 else if ("fr".equals(lang))
339 else if ("it".equals(lang))
341 else if ("nl".equals(lang))
343 else if ("fi".equals(lang))
345 else if ("sv".equals(lang))
357 * Returns the full name of this font face, for example
358 * <i>“Univers Light”</i>.
360 * @param locale the locale for which to localize the name.
362 * @return the face name.
364 public synchronized String getFullName(Locale locale)
369 locale = Locale.getDefault();
371 name = getName(NameDecoder.NAME_FULL, locale);
373 name = getName(NameDecoder.NAME_FULL, Locale.ENGLISH);
375 name = getName(NameDecoder.NAME_FULL, /* any language */ null);
382 * Returns the PostScript name of this font face, for example
383 * <i>“Univers-Light”</i>.
385 * @return the PostScript name, or <code>null</code> if the font
386 * does not provide a PostScript name.
388 public synchronized String getPostScriptName()
390 return getName(NameDecoder.NAME_POSTSCRIPT, /* any language */ null);
395 * Returns the number of glyphs in this font face.
397 public int getNumGlyphs()
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.
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.
412 public int getMissingGlyphCode()
414 /* No synchronization is needed because the result is constant. */
420 * The font’s name table, or <code>null</code> if this
421 * table has not yet been accessed.
423 private ByteBuffer nameTable;
427 * Extracts a String from the font’s name table.
429 * @param name the numeric TrueType or OpenType name ID.
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).
436 private String getName(int name, Locale locale)
438 if (nameTable == null)
439 nameTable = getFontTable(OpenType.TAG_NAME);
440 return NameDecoder.getName(nameTable, name, locale);
445 * Returns the version of the font.
447 * @see java.awt.font.OpenType#getVersion
449 * @return the version in 16.16 fixed-point encoding, for example
450 * 0x00010000 for version 1.0.
452 public int getVersion()
454 /* No synchronization is needed because the version is set in the
455 * constructor, and it cannot change during the lifetime of the
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.
467 * @param tag the table identifier, for example
468 * <code>OpenType.GLYF</code>.
470 * @return a slice of the underlying buffer containing the table, or
471 * <code>null</code> if the font does not contain the requested
474 public synchronized ByteBuffer getFontTable(int tag)
476 int index, start, len;
479 index = getTableIndex(tag);
483 start = tableStart[index];
484 len = tableLength[index];
485 buf.limit(start + len).position(start);
486 result = buf.slice();
493 * Returns the size of one of the tables in the font,
494 * or -1 if the table does not exist.
496 public int getFontTableSize(int tag)
498 int index = getTableIndex(tag);
501 return tableLength[index];
505 private CharGlyphMap getCharGlyphMap()
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);
526 * Looks up a glyph in the font’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.
532 * <p>It is safe to call this method from any thread.
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.
538 * @return the glyph index, or zero if the font does not contain
539 * a glyph for the specified codepoint.
541 public int getGlyph(int ucs4)
543 return getCharGlyphMap().getGlyph(ucs4);
548 * Creates a GlyphVector by mapping each character in a
549 * CharacterIterator to the corresponding glyph.
551 * <p>The mapping takes only the font’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
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.
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>.
575 * @param ci a CharacterIterator for iterating over the
576 * characters to be displayed.
578 public synchronized GlyphVector createGlyphVector(Font font,
579 FontRenderContext frc,
580 CharacterIterator ci)
588 cmap = getCharGlyphMap();
589 numGlyphs = ci.getEndIndex() - ci.getBeginIndex();
590 glyphs = new int[numGlyphs];
592 for (c = ci.first(); c != CharacterIterator.DONE; c = ci.next())
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);
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.
605 if (glyph != numGlyphs)
607 int[] newGlyphs = new int[glyph];
608 System.arraycopy(glyphs, 0, newGlyphs, 0, glyph);
612 return new GNUGlyphVector(this, font, frc, glyphs);
618 * Determines the advance width for a glyph.
620 * @param glyphIndex the glyph whose advance width is to be
623 * @param pointSize the point size of the font.
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
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.
635 * @param fractionalMetrics <code>true</code> for fractional metrics,
636 * <code>false</code> for rounding the result to a pixel boundary.
638 * @param horizontal <code>true</code> for horizontal line layout,
639 * <code>false</code> for vertical line layout.
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
647 public synchronized void getAdvance(int glyphIndex,
649 AffineTransform transform,
651 boolean fractionalMetrics,
655 /* Delegate the measurement to the scaler. The synchronization is
656 * needed because the scaler is not synchronized.
658 scaler.getAdvance(glyphIndex, pointSize, transform,
659 antialias, fractionalMetrics, horizontal,
665 * Returns the shape of a glyph.
667 * @param glyph the glyph whose advance width is to be determined
669 * @param pointSize the point size of the font.
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
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.
681 * @param fractionalMetrics <code>true</code> for fractional
682 * metrics, <code>false</code> for rounding the result to a pixel
685 * @return the scaled and grid-fitted outline of the specified
686 * glyph, or <code>null</code> for bitmap fonts.
688 public synchronized GeneralPath getGlyphOutline(int glyph,
690 AffineTransform transform,
692 boolean fractionalMetrics)
694 /* The synchronization is needed because the scaler is not
697 return scaler.getOutline(glyph, pointSize, transform,
698 antialias, fractionalMetrics);
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.
705 * @param glyph the glyph index to fetch
706 * @param transform the transform to apply
708 * @return the raw outline of that glyph
710 public synchronized Zone getRawGlyphOutline(int glyph,
711 AffineTransform transform)
713 return scaler.getRawOutline(glyph, transform);
717 * Returns a name for the specified glyph. This is useful for
718 * generating PostScript or PDF files that embed some glyphs of a
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
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.
736 * @param glyphIndex the glyph whose name the caller wants to
739 public synchronized String getGlyphName(int glyphIndex)
741 if (glyphNamer == null)
742 glyphNamer = GlyphNamer.forTables(numGlyphs,
743 getFontTable(OpenType.TAG_POST),
744 getFontTable(TAG_ZAPF));
746 return glyphNamer.getGlyphName(glyphIndex);
751 * Determines the distance between the base line and the highest
754 * @param pointSize the point size of the font.
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
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.
766 * @param fractionalMetrics <code>true</code> for fractional metrics,
767 * <code>false</code> for rounding the result to a pixel boundary.
769 * @param horizontal <code>true</code> for horizontal line layout,
770 * <code>false</code> for vertical line layout.
772 * @return the ascent, which usually is a positive number.
774 public synchronized float getAscent(float pointSize,
775 AffineTransform transform,
777 boolean fractionalMetrics,
780 return scaler.getAscent(pointSize, transform,
781 antialiased, fractionalMetrics,
787 * Determines the distance between the base line and the lowest
790 * @param pointSize the point size of the font.
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
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.
802 * @param fractionalMetrics <code>true</code> for fractional metrics,
803 * <code>false</code> for rounding the result to a pixel boundary.
805 * @param horizontal <code>true</code> for horizontal line layout,
806 * <code>false</code> for vertical line layout.
808 * @return the descent, which usually is a nagative number.
810 public synchronized float getDescent(float pointSize,
811 AffineTransform transform,
813 boolean fractionalMetrics,
816 return scaler.getDescent(pointSize, transform,
817 antialiased, fractionalMetrics,
823 * Converts a four-byte tag identifier into a String that can be
824 * displayed when debugging this class.
826 * @param tag the tag as an <code>int</code>.
828 * @return the tag in human-readable form, for example
829 * <code>name</code> or <code>glyf</code>.
831 static String tagToString(int tag)
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);