/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* TrueTypeFont is not called SFntFont because it is not expected
* to handle all types that may be housed in a such a font file.
* If additional types are supported later, it may make sense to
* create an SFnt superclass. Eg to handle sfnt-housed postscript fonts.
* OpenType fonts are handled by this class, and possibly should be
* represented by a subclass.
* An instance stores some information from the font file to faciliate
* faster access. File size, the table directory and the names of the font
* are the most important of these. It amounts to approx 400 bytes
* for a typical font. Systems with mutiple locales sometimes have up to 400
* font files, and an app which loads all font files would need around
* 160Kbytes. So storing any more info than this would be expensive.
*/
/* -- Tags for required TrueType tables */
/* -- Tags for opentype related tables */
/* -- Tags for non-standard tables */
/* -- Other tags */
/* -- ID's used in the 'name' table */
/* MS locale id for US English is the "default" */
// public static final int STYLE_WEIGHT_ID = 2; // currently unused.
class DirectoryEntry {
int tag;
int offset;
int length;
}
/* There is a pool which limits the number of fd's that are in
* use. Normally fd's are closed as they are replaced in the pool.
* But if an instance of this class becomes unreferenced, then there
* needs to be a way to close the fd. A finalize() method could do this,
* but using the Disposer class will ensure its called in a more timely
* manner. This is not something which should be relied upon to free
* fd's - its a safeguard.
*/
public synchronized void dispose() {
try {
}
} catch (IOException e) {
} finally {
}
}
}
/* > 0 only if this font is a part of a collection */
/* Number of fonts in this collection. ==1 if not a collection */
/* offset in file of table directory for this font */
int numTables;
// protected byte []gposTable = null;
// protected byte []gdefTable = null;
// protected byte []gsubTable = null;
// protected byte []mortTable = null;
// protected boolean hintsTabledChecked = false;
// protected boolean containsHintsTable = false;
/* These fields are set from os/2 table info. */
private boolean supportsJA;
private boolean supportsCJK;
/* These are for faster access to the name of the font as
* typically exposed via API to applications.
*/
/**
* - does basic verification of the file
* - reads the header table for this font (within a collection)
* - reads the names (full, family).
* - determines the style of the font.
* - initializes the CMAP
* @throws FontFormatException - if the font can't be opened
* or fails verification, or there's no usable cmap
*/
boolean javaRasterizer)
throws FontFormatException {
super(platname, nativeNames);
try {
verify();
} catch (Throwable t) {
close();
if (t instanceof FontFormatException) {
throw (FontFormatException)t;
} else {
throw new FontFormatException("Unexpected runtime exception.");
}
}
}
/* Enable natives just for fonts picked up from the platform that
* may have external bitmaps on Solaris. Could do this just for
* the fonts that are specified in font configuration files which
* would lighten the burden (think about that).
* The EBLCTag is used to skip natives for fonts that contain embedded
* bitmaps as there's no need to use X11 for those fonts.
* Skip all the latin fonts as they don't need this treatment.
* Further refine this to fonts that are natively accessible (ie
* as PCF bitmap fonts on the X11 font path).
* This method is called when creating the first strike for this font.
*/
protected boolean checkUseNatives() {
if (checkedNatives) {
return useNatives;
}
checkedNatives = true;
return false; /* useNatives is false */
} else if (nativeNames instanceof String) {
/* Don't do do this for Latin fonts */
checkedNatives = true;
return false;
try {
/* If reach here we have an non-latin font that has
* external bitmaps and we successfully created it.
*/
useNatives = true;
} catch (FontFormatException e) {
nativeFonts = null;
}
}
} else if (nativeNames instanceof String[]) {
boolean externalBitmaps = false;
checkedNatives = true;
return false;
externalBitmaps = true;
}
}
if (!externalBitmaps) {
checkedNatives = true;
return false;
}
useNatives = true;
try {
} catch (FontFormatException e) {
useNatives = false;
nativeFonts = null;
}
}
}
if (useNatives) {
}
checkedNatives = true;
return useNatives;
}
/* This is intended to be called, and the returned value used,
* from within a block synchronized on this font object.
* ie the channel returned may be nulled out at any time by "close()"
* unless the caller holds a lock.
* Deadlock warning: FontManager.addToPool(..) acquires a global lock,
* which means nested locks may be in effect.
*/
if (FontUtilities.isLogging()) {
}
try {
try {
} catch (FileNotFoundException ffne) {
}
return null;
}
});
if (fm instanceof SunFontManager) {
}
} catch (NullPointerException e) {
close();
throw new FontFormatException(e.toString());
} catch (ClosedChannelException e) {
/* NIO I/O is interruptible, recurse to retry operation.
* The call to channel.size() above can throw this exception.
* Clear interrupts before recursing in case NIO didn't.
* Note that close() sets disposerRecord.channel to null.
*/
close();
open();
} catch (IOException e) {
close();
throw new FontFormatException(e.toString());
}
}
return disposerRecord.channel;
}
protected synchronized void close() {
}
int bread = 0;
try {
synchronized (this) {
open();
}
/* Since the caller ensures that offset is < fileSize
* this condition suggests that fileSize is now
* different than the value we originally provided
* to native when the scaler was created.
* Also fileSize is updated every time we
* open() the file here, but in native the value
* isn't updated. If the file has changed whilst we
* are executing we want to bail, not spin.
*/
if (FontUtilities.isLogging()) {
" file size is " + fileSize+
" file is " + platName;
}
return -1;
} else {
}
}
if (cnt == -1) {
" and now is " + currSize;
}
if (FontUtilities.isLogging()) {
}
// We could still flip() the buffer here because
// it's possible that we did read some data in
// an earlier loop, and we probably should
// return that to the caller. Although if
// the caller expected 8K of data and we return
// only a few bytes then maybe it's better instead to
// set bread = -1 to indicate failure.
// The following is therefore using arbitrary values
// but is meant to allow cases where enough
// data was read to probably continue.
if (FontUtilities.isLogging()) {
" bytes instead of " + length;
}
} else {
bread = -1;
}
throw new IOException(msg);
}
}
}
}
} catch (FontFormatException e) {
if (FontUtilities.isLogging()) {
"While reading " + platName, e);
}
} catch (ClosedChannelException e) {
/* NIO I/O is interruptible, recurse to retry operation.
* Clear interrupts before recursing in case NIO didn't.
*/
close();
} catch (IOException e) {
/* If we did not read any bytes at all and the exception is
* not a recoverable one (ie is not ClosedChannelException) then
* we should indicate that there is no point in re-trying.
* Other than an attempt to read past the end of the file it
* seems unlikely this would occur as problems opening the
* file are handled as a FontFormatException.
*/
if (FontUtilities.isLogging()) {
"While reading " + platName, e);
}
if (bread == 0) {
}
}
return bread;
}
try {
synchronized (this) {
open();
}
return null; // assert?
} else {
}
}
}
} catch (FontFormatException e) {
return null;
} catch (ClosedChannelException e) {
/* NIO I/O is interruptible, recurse to retry operation.
* Clear interrupts before recursing in case NIO didn't.
*/
close();
} catch (IOException e) {
return null;
}
return buffer;
}
/* This is used by native code which can't allocate a direct byte
* buffer because of bug 4845371. It, and references to it in native
* code in scalerMethods.c can be removed once that bug is fixed.
* 4845371 is now fixed but we'll keep this around as it doesn't cost
*/
} else {
return bufferBytes;
}
}
open();
}
int headerOffset = 0;
try {
case ttcfTag:
if (fIndex >= directoryCount) {
throw new FontFormatException("Bad collection index");
}
break;
case v1ttTag:
case trueTag:
case ottoTag:
break;
default:
throw new FontFormatException("Unsupported sfnt " +
}
/* Now have the offset of this TT font (possibly within a TTC)
* representing the number of tables in the table directory.
* The table directory begins at 12 bytes after the header.
* Each table entry is 16 bytes long (4 32-bit ints)
*/
for (int i=0; i<numTables;i++) {
}
}
initNames();
} catch (Exception e) {
if (FontUtilities.isLogging()) {
}
if (e instanceof FontFormatException) {
throw (FontFormatException)e;
} else {
throw new FontFormatException(e.toString());
}
}
throw new FontFormatException("Font name not found");
}
/* The os2_Table is needed to gather some info, but we don't
* want to keep it around (as a field) so obtain it once and
* pass it to the code that needs it.
*/
}
/* The array index corresponds to a bit offset in the TrueType
* font's OS/2 compatibility table's code page ranges fields.
* These are two 32 bit unsigned int fields at offsets 78 and 82.
* We are only interested in determining if the font supports
* the windows encodings we expect as the default encoding in
* supported locales, so we only map the first of these fields.
*/
"cp1252", /* 0:Latin 1 */
"cp1250", /* 1:Latin 2 */
"cp1251", /* 2:Cyrillic */
"cp1253", /* 3:Greek */
"cp1255", /* 5:Hebrew */
"cp1256", /* 6:Arabic */
"cp1257", /* 7:Windows Baltic */
"", /* 8:reserved for alternate ANSI */
"", /* 9:reserved for alternate ANSI */
"", /* 10:reserved for alternate ANSI */
"", /* 11:reserved for alternate ANSI */
"", /* 12:reserved for alternate ANSI */
"", /* 13:reserved for alternate ANSI */
"", /* 14:reserved for alternate ANSI */
"", /* 15:reserved for alternate ANSI */
"ms874", /* 16:Thai */
"gbk", /* 18:PRC GBK Cp950 */
"ms949", /* 19:Korean Extended Wansung */
"ms950", /* 20:Chinese (Taiwan, Hongkong, Macau) */
"ms1361", /* 21:Korean Johab */
"", /* 22 */
"", /* 23 */
"", /* 24 */
"", /* 25 */
"", /* 26 */
"", /* 27 */
"", /* 28 */
"", /* 29 */
"", /* 30 */
"", /* 31 */
};
/* This maps two letter language codes to a Windows code page.
* Note that eg Cp1252 (the first subarray) is not exactly the same as
* Latin-1 since Windows code pages are do not necessarily correspond.
* There are two codepages for zh and ko so if a font supports
* only one of these ranges then we need to distinguish based on
* country. So far this only seems to matter for zh.
* REMIND: Unicode locales such as Hindi do not have a code page so
* this whole mechansim needs to be revised to map languages to
* the Unicode ranges either when this fails, or as an additional
* validating test. Basing it on Unicode ranges should get us away
* from needing to map to this small and incomplete set of Windows
* code pages which looks odd on non-Windows platforms.
*/
{ "en", "ca", "da", "de", "es", "fi", "fr", "is", "it",
"nl", "no", "pt", "sq", "sv", },
{ "cs", "cz", "et", "hr", "hu", "nr", "pl", "ro", "sk",
"sl", "sq", "sr", },
{ "bg", "mk", "ru", "sh", "uk" },
{ "el" },
{ "tr" },
{ "he" },
{ "ar" },
{ "et", "lt", "lv" },
{ "th" },
{ "ja" },
{ "zh", "zh_CN", },
{ "ko" },
{ "zh_HK", "zh_TW", },
{ "ko" },
};
"cp1252",
"cp1250",
"cp1251",
"cp1253",
"cp1254",
"cp1255",
"cp1256",
"cp1257",
"ms874",
"ms932",
"gbk",
"ms949",
"ms950",
"ms1361",
};
if (defaultCodePage != null) {
return defaultCodePage;
}
if (FontUtilities.isWindows) {
} else {
throw new InternalError("wrong code pages array length");
}
}
}
defaultCodePage = codePages[i];
return defaultCodePage;
}
}
}
}
}
if (defaultCodePage == null) {
defaultCodePage = "";
}
return defaultCodePage;
}
/* Theoretically, reserved bits must not be set, include symbol bits */
encoding = getCodePage();
}
return false;
}
/* java_props_md.c has a couple of special cases
* if language packs are installed. In these encodings the
* fontconfig files pick up different fonts :
* SimSun-18030 and MingLiU_HKSCS. Since these fonts will
* indicate they support the base encoding, we need to rewrite
*/
encoding = "gbk";
encoding = "ms950";
}
/* required info is at offsets 78 and 82 */
return false;
}
/* This test is too stringent for Arial on Solaris (and perhaps
* other fonts). Arial has at least one reserved bit set for an
* unknown reason.
*/
// if (((range1 & reserved_bits1) | (range2 & reserved_bits2)) != 0) {
// return false;
// }
return true;
}
}
}
return false;
}
/* Use info in the os_2Table to test CJK support */
/* required info is in ulong at offset 46 */
return;
}
/* Any of these bits set in the 32-63 range indicate a font with
* support for a CJK range. We aren't looking at some other bits
* in the 64-69 range such as half width forms as its unlikely a font
* would include those and none of these.
*/
/* This should be generalised, but for now just need to know if
* Hiragana or Katakana ranges are supported by the font.
* In the 4 longs representing unicode ranges supported
* bits 49 & 50 indicate hiragana and katakana
* This is bits 17 & 18 in the 2nd ulong. If either is supported
* we presume this is a JA font.
*/
}
boolean supportsJA() {
return supportsJA;
}
for (int i=0;i<numTables;i++) {
entry = tableDirectory[i];
break;
}
}
return null;
}
int bread = 0;
synchronized (this) {
try {
open();
}
} catch (ClosedChannelException e) {
/* NIO I/O is interruptible, recurse to retry operation.
* Clear interrupts before recursing in case NIO didn't.
*/
close();
return getTableBuffer(tag);
} catch (IOException e) {
return null;
} catch (FontFormatException e) {
return null;
}
return null;
} else {
return buffer;
}
}
}
/* NB: is it better to move declaration to Font2D? */
long getLayoutTableCache() {
try {
return getScaler().getLayoutTableCache();
} catch(FontScalerException fe) {
return 0L;
}
}
return null;
try {
}
}
return data;
}
for (int i=0;i<numTables;i++) {
return tableDirectory[i].length;
}
}
return 0;
}
for (int i=0;i<numTables;i++) {
return tableDirectory[i].offset;
}
}
return 0;
}
for (int i=0;i<numTables;i++) {
return tableDirectory[i];
}
}
return null;
}
/* Used to determine if this size has embedded bitmaps, which
* for CJK fonts should be used in preference to LCD glyphs.
*/
if (!supportsCJK) {
return false;
}
return false;
}
/* The bitmapSizeTable's start at offset of 8.
* Each bitmapSizeTable entry is 48 bytes.
* The offset of ppemY in the entry is 45.
*/
for (int i=0;i<numSizes;i++) {
return true;
}
}
return false;
}
return fullName;
}
/* This probably won't get called but is there to support the
* contract() of setStyle() defined in the superclass.
*/
protected void setStyle() {
}
/* TrueTypeFont can use the fsSelection fields of OS/2 table
* to determine the style. In the unlikely case that doesn't exist,
* can use macStyle in the 'head' table but simpler to
* fall back to super class algorithm of looking for well known string.
* A very few fonts don't specify this information, but I only
* came across one: Lucida Sans Thai Typewriter Oblique in
* that explicitly specified the wrong value. It says its regular.
* I didn't find any fonts that were inconsistent (ie regular plus some
* other value).
*/
/* fsSelection is unsigned short at buffer offset 62 */
super.setStyle();
return;
}
// System.out.println("platname="+platName+" font="+fullName+
// " family="+familyName+
// " R="+regular+" I="+italic+" B="+bold);
/* This is inconsistent. Try using the font name algorithm */
super.setStyle();
return;
/* No style specified. Try using the font name algorithm */
super.setStyle();
return;
}
case fsSelectionItalicBit:
break;
case fsSelectionBoldBit:
/* Workaround for Solaris's use of a JA font that's marked as
* being designed bold, but is used as a PLAIN font.
*/
} else {
}
break;
}
}
stSize = .05f;
stPos = -.4f;
return;
}
}
ulSize = .05f;
ulPos = .1f;
return;
}
}
int upem = -1;
}
}
}
/* Check for fonts using encodings 2->6 is just for
* some old DBCS fonts, apparently mostly on Solaris.
* Some of these fonts encode ascii names as double-byte characters.
* ie with a leading zero byte for what properly should be a
* single byte-char.
*/
len = 0;
for (int i=0; i<oldlen; i++) {
if (oldbytes[i] != 0) {
}
}
}
switch (encoding) {
default: charset = "UTF-16"; break;
}
try {
} catch (UnsupportedEncodingException e) {
if (FontUtilities.isLogging()) {
}
} catch (Throwable t) {
return null;
}
}
protected void initNames() {
byte[] name = new byte[256];
/* The name table uses unsigned shorts. Many of these
* are known small values that fit in a short.
* The values that are sizes or offsets into the table could be
* greater than 32767, so read and store those as ints
*/
for (int i=0; i<numRecords; i++) {
if (platformID != MS_PLATFORM_ID) {
continue; // skip over this record.
}
switch (nameID) {
case FAMILY_NAME_ID:
langID == nameLocaleID)
{
}
if (langID == nameLocaleID) {
}
}
/*
for (int ii=0;ii<nameLen;ii++) {
int val = (int)name[ii]&0xff;
System.err.print(Integer.toHexString(val)+ " ");
}
System.err.println();
System.err.println("familyName="+familyName +
" nameLen="+nameLen+
" langID="+langID+ " eid="+encodingID +
" str len="+familyName.length());
*/
break;
case FULL_NAME_ID:
langID == nameLocaleID)
{
}
if (langID == nameLocaleID) {
}
}
break;
}
}
if (localeFamilyName == null) {
}
if (localeFullName == null) {
}
}
}
/* Return the requested name in the requested locale, for the
* MS platform ID. If the requested locale isn't found, return US
* English, if that isn't found, return null and let the caller
* figure out how to handle that.
*/
byte[] name = new byte[1024];
/* The name table uses unsigned shorts. Many of these
* are known small values that fit in a short.
* The values that are sizes or offsets into the table could be
* greater than 32767, so read and store those as ints
*/
for (int i=0; i<numRecords; i++) {
if (platformID != MS_PLATFORM_ID) {
continue; // skip over this record.
}
if (nameID == findNameID &&
|| langID == findLocaleID)) {
if (langID == findLocaleID) {
return foundName;
}
}
}
}
return foundName;
}
/**
* @return number of logical fonts. Is "1" for all but TTC files
*/
public int getFontCount() {
return directoryCount;
}
}
return scaler;
}
/* Postscript name is rarely requested. Don't waste cycles locating it
* as part of font creation, nor storage to hold it. Get it only on demand.
*/
return fullName;
} else {
return name;
}
}
return fullName;
return localeFullName;
} else {
return fullName;
} else {
return name;
}
}
}
// Return a Microsoft LCID from the given Locale.
// Used when getting localized font data.
}
private static synchronized void createLCIDMap() {
return;
}
// the following statements are derived from the langIDMap
// awk script:
// $1~/\/\*/ { next}
// $3~/\?\?/ { next }
// $3!~/_/ { next }
// $1~/0x0409/ { next }
// $1~/0x0c0a/ { next }
// $1~/0x042c/ { next }
// $1~/0x0443/ { next }
// $1~/0x0812/ { next }
// $1~/0x04/ { print " addLCIDMapEntry(map, " substr($3, 0, 3) "\", (short) " substr($1, 0, 6) ");" ; next }
// $3~/,/ { print " addLCIDMapEntry(map, " $3 " (short) " substr($1, 0, 6) ");" ; next }
// { print " addLCIDMapEntry(map, " $3 ", (short) " substr($1, 0, 6) ");" ; next }
// The lines of this script:
// - eliminate comments
// - eliminate questionable locales
// - eliminate language-only locales
// - eliminate the default LCID value
// - eliminate a few other unneeded LCID values
// - print language-only locale entries for x04* LCID values
// (apparently Microsoft doesn't use language-only LCID values -
// - print complete entries for all other LCID values
// Run
// awk -f awk-script langIDMap > statements
}
// optimize for common case
return US_LCID;
}
}
if (lcidObject != null) {
return lcidObject.shortValue();
}
if (pos < 1) {
return US_LCID;
}
}
return US_LCID;
}
return familyName;
return localeFamilyName;
} else {
return familyName;
} else {
return name;
}
}
}
mapper = new TrueTypeGlyphMapper(this);
}
return mapper;
}
/* This duplicates initNames() but that has to run fast as its used
* during typical start-up and the information here is likely never
* needed.
*/
byte[] name = new byte[256];
/* The name table uses unsigned shorts. Many of these
* are known small values that fit in a short.
* The values that are sizes or offsets into the table could be
* greater than 32767, so read and store those as ints
*/
for (int i=0; i<numRecords; i++) {
if (platformID != MS_PLATFORM_ID) {
continue; // skip over this record.
}
if (nameID == requestedID) {
}
}
}
}
try {
} catch (Exception e) {
/* In case of malformed font */
}
}
try {
} catch (Exception e) {
/* In case of malformed font */
}
}
/* Used by the OpenType engine for mark positioning.
*/
try {
} catch(FontScalerException fe) {
return null;
}
}
private char[] gaspTable;
private char[] getGaspTable() {
return gaspTable;
}
return gaspTable = new char[0];
}
/* format "1" has appeared for some Windows Vista fonts.
* Its presently undocumented but the existing values
* seem to be still valid so we can use it.
*/
return gaspTable = new char[0];
}
return gaspTable = new char[0];
}
return gaspTable;
}
/* This is to obtain info from the TT 'gasp' (grid-fitting and
* scan-conversion procedure) table which specifies three combinations:
* Hint, Smooth (greyscale), Hint and Smooth.
* In this simplified scheme we don't distinguish the latter two. We
* hint even at small sizes, so as to preserve metrics consistency.
* If the information isn't available default values are substituted.
* The more precise defaults we'd do if we distinguished the cases are:
* Bold (no other style) fonts :
* 0-8 : Smooth ( do grey)
* 9+ : Hint + smooth (gridfit + grey)
* Plain, Italic and Bold-Italic fonts :
* 0-8 : Smooth ( do grey)
* 9-17 : Hint (gridfit)
* 18+ : Hint + smooth (gridfit + grey)
* The defaults should rarely come into play as most TT fonts provide
* better defaults.
* REMIND: consider unpacking the table into an array of booleans
* for faster use.
*/
char[] gasp = getGaspTable();
}
}
return true;
}
return true;
} else {
}
}
public boolean hasSupplementaryChars() {
}
}
}