Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1850 lines
62 KiB

/*
* Adobe Universal Font Library
*
* Copyright (c) 1996 Adobe Systems Inc.
* All Rights Reserved
*
* ParseTT.c
*
*
* $Header:
*/
/*=============================================================================*
* Include files used by this interface *
*=============================================================================*/
#include "UFLPriv.h"
#include "ParseTT.h"
#include "UFOT42.h"
#include "UFLMem.h"
#include "UFLMath.h"
#include "UFLStd.h"
#include "UFLErr.h"
#include "UFLPS.h"
#include "ttformat.h"
/******************************************************************************
'cmap' table defintion
- from TTF format spec -
This table defines the mapping of character codes to the glyph index values
used in the font. It may contain more than one subtable, in order to support
more than one character encoding scheme. Character codes that do not correspond
to any glyph in the font should be mapped to glyph index 0. The glyph at this
location must be a special glyph representing a missing character.
The table header indicates the character encodings for which subtables are
present. Each subtable is in one of four possible formats and begins with a
format code indicating the format used.
The platform ID and platform-specific encoding ID are used to specify the
subtable; this means that each platform ID/platform-specific encoding ID pair
may only appear once in the cmap table. Each subtable can specify a different
character encoding. (See the 'name' table section). The entries must be sorted
first by platform ID and then by platform-specific encoding ID.
When building a Unicode font for Windows, the platform ID should be 3 and the
encoding ID should be 1. When building a symbol font for Windows, the platform
ID should be 3 and the encoding ID should be 0. When building a font that will
be used on the Macintosh, the platform ID should be 1 and the encoding ID
should be 0.
All Microsoft Unicode encodings (Platform ID = 3, Encoding ID = 1) must use
Format 4 for their 'cmap' subtable. Microsoft strongly recommends using a
Unicode 'cmap' for all fonts. However, some other encodings that appear in
current fonts follow:
Platform ID Encoding ID Description
1 0 Mac
3 0 Symbol
3 1 Unicode
3 2 ShiftJIS
3 3 Big5
3 4 PRC
3 5 Wansung
3 6 Johab
The Character To Glyph Index Mapping Table is organized as follows:
Type Description
USHORT Table version number (0).
USHORT Number of encoding tables, n.
This is followed by an entry for each of the n encoding table specifying the
particular encoding, and the offset to the actual subtable:
Type Description
USHORT Platform ID.
USHORT Platform-specific encoding ID.
ULONG Byte offset from beginning of table to the subtable for this
encoding.
Format 0: Byte encoding table
===============================================================================
This is the Apple standard character to glyph index mapping table.
Type Name Description
USHORT format Format number is set to 0.
USHORT length This is the length in bytes of the subtable.
USHORT version Version number (starts at 0).
BYTE glyphIdArray[256] An array that maps character codes to glyph index
values.
This is a simple 1 to 1 mapping of character codes to glyph indices. The glyph
set is limited to 256. Note that if this format is used to index into a larger
glyph set, only the first 256 glyphs will be accessible.
Format 2: High-byte mapping through table
===============================================================================
This subtable is useful for the national character code standards used for
Japanese, Chinese, and Korean characters. These code standards use a mixed
8/16-bit encoding, in which certain byte values signal the first byte of a
2-byte character (but these values are also legal as the second byte of a
2-byte character). Character codes are always 1-byte. The glyph set is limited
to 256. In addition, even for the 2-byte characters, the mapping of character
codes to glyph index values depends heavily on the first byte. Consequently,
the table begins with an array that maps the first byte to a 4-word subHeader.
For 2-byte character codes, the subHeader is used to map the second byte's
value through a subArray, as described below. When processing mixed 8/16-bit
text, subHeader 0 is special: it is used for single-byte character codes.
When subHeader zero is used, a second byte is not needed; the single byte
value is mapped through the subArray.
Type Name Description
USHORT format Format number is set to 2.
USHORT length Length in bytes.
USHORT version Version number (starts at 0)
USHORT subHeaderKeys[256] Array that maps high bytes to subHeaders:
value is subHeader index * 8.
4 words struct subHeaders[] Variable-length array of subHeader structures.
4 words-struct subHeaders[]
USHORT glyphIndexArray[ ] Variable-length array containing subarrays used
for mapping the low byte of 2-byte characters.
A subHeader is structured as follows:
Type Name Description
USHORT firstCode First valid low byte for this subHeader.
USHORT entryCount Number of valid low bytes for this subHeader.
SHORT idDelta See text below.
USHORT idRangeOffset See text below.
The firstCode and entryCount values specify a subrange that begins at firstCode
and has a length equal to the value of entryCount. This subrange stays within
the 0 255 range of the byte being mapped. Bytes outside of this subrange are
mapped to glyph index 0 (missing glyph).The offset of the byte within this
subrange is then used as index into a corresponding subarray of
glyphIndexArray. This subarray is also of length entryCount. The value of the
idRangeOffset is the number of bytes past the actual location of the
idRangeOffset word where the glyphIndexArray element corresponding to firstCode
appears.
Finally, if the value obtained from the subarray is not 0 (which indicates the
missing glyph), you should add idDelta to it in order to get the glyphIndex.
The value idDelta permits the same subarray to be used for several different
subheaders. The idDelta arithmetic is modulo 65536.
Format 4: Segment mapping to delta values
=====================================================
This is the Microsoft standard character to glyph index mapping table.
This format is used when the character codes for the characters represented by
a font fall into several contiguous ranges, possibly with holes in some or all
of the ranges (that is, some of the codes in a range may not have a
representation in the font). The format-dependent data is divided into three
parts, which must occur in the following order:
1. A four-word header gives parameters for an optimized search of the
segment list;
2. Four parallel arrays describe the segments (one segment for each
contiguous range of codes);
3. A variable-length array of glyph IDs (unsigned words).
Type Name Description
USHORT format Format number is set to 4.
USHORT length Length in bytes.
USHORT version Version number (starts at 0).
USHORT segCountX2 2 x segCount.
USHORT searchRange 2 x (2**floor(log2(segCount)))
USHORT entrySelector log2(searchRange/2)
USHORT rangeShift 2 x segCount - searchRange
USHORT endCount[segCount] End characterCode for each segment,
last = 0xFFFF.
USHORT reservedPad Set to 0.
USHORT startCount[segCount] Start character code for each segment.
USHORT idDelta[segCount] Delta for all character codes in segment.
USHORT idRangeOffset[segCount] Offsets into glyphIdArray or 0
USHORT glyphIdArray[ ] Glyph index array (arbitrary length)
The number of segments is specified by segCount, which is not explicitly in the
header; however, all of the header parameters are derived from it. The
searchRange value is twice the largest power of 2 that is less than or equal to
segCount. For example, if segCount=39, we have the following:
segCountX2 78
searchRange 64 (2 * largest power of 2 £ 39)
entrySelector 5 log2(32)
rangeShift 14 2 x 39 - 64
Each segment is described by a startCode and endCode, along with an idDelta
and an idRangeOffset, which are used for mapping the character codes in the
segment. The segments are sorted in order of increasing endCode values, and the
segment values are specified in four parallel arrays. You search for the first
endCode that is greater than or equal to the character code you want to map. If
the corresponding startCode is less than or equal to the character code, then
you use the corresponding idDelta and idRangeOffset to map the character code
to a glyph index (otherwise, the missingGlyph is returned). For the search to
terminate, the final endCode value must be 0xFFFF. This segment need not
contain any valid mappings. (It can just map the single character code 0xFFFF
to missingGlyph). However, the segment must be present. If the idRangeOffset
value for the segment is not 0, the mapping of character codes relies on
glyphIdArray. The character code offset from startCode is added to the
idRangeOffset value. This sum is used as an offset from the current location
within idRangeOffset itself to index out the correct glyphIdArray value. This
obscure indexing trick works because glyphIdArray immediately follows
idRangeOffset in the font file. The C expression that yields the glyph index
is:
*(idRangeOffset[i]/2 + (c - startCount[i]) + &idRangeOffset[i])
The value c is the character code in question, and i is the segment index in
which c appears. If the value obtained from the indexing operation is not 0
(which indicates missingGlyph), idDelta[i] is added to it to get the glyph
index. The idDelta arithmetic is modulo 65536.
If the idRangeOffset is 0, the idDelta value is added directly to the character
code offset (i.e. idDelta[i] + c) to get the corresponding glyph index. Again,
the idDelta arithmetic is modulo 65536.
As an example, the variant part of the table to map characters 10-20, 30-90,
and 100-153 onto a contiguous range of glyph indices may look like this:
segCountX2: 8
searchRange: 8
entrySelector: 4
rangeShift: 0
endCode: 20 90 153 0xFFFF
reservedPad: 0
startCode: 10 30 100 0xFFFF
idDelta: -9 -18 -27 1
idRangeOffset: 0 0 0 0
This table performs the following mappings:
10 -> 10 - 9 = 1
20 -> 20 - 9 = 11
30 -> 30 - 18 = 12
90 -> 90 - 18 = 72
...and so on.
Note that the delta values could be reworked so as to reorder the segments.
Format 6: Trimmed table mapping
===============================================================================
Type Name Description
USHORT format Format number is set to 6.
USHORT length Length in bytes.
USHORT version Version number (starts at 0)
USHORT firstCode First character code of subrange.
USHORT entryCount Number of character codes in subrange.
USHORT glyphIdArray [entryCount] Array of glyph index values for
character codes in the range.
The firstCode and entryCount values specify a subrange (beginning at firstCode,
length = entryCount) within the range of possible character codes. Codes
outside of this subrange are mapped to glyph index 0. The offset of the code
(from the first code) within this subrange is used as index to the
glyphIdArray, which provides the glyph index value.
*******************************************************************************/
/******************************************************************************
* TTC Header Table
*
* TAG TTCTag TrueType Collection ID string:
* 'ttcf'
* FIXED32 Version Version of the TTC Header table
* (initially 0x00010000)
* ULONG Directory Count Number of Table Directories in TTC
* ULONG TableDirectory[DirectoryCount] Array of offsets to Table Directories
* from file begin
******************************************************************************/
/*
* NameID=3 is for unique Name such as "MonoType:Times New Roman:1990" which
* will be used to identify correct Font in a TTC file.
*/
#define NAMEID_FACENAME 3
#define MAC_PLATFORM 1
#define MS_PLATFORM 3
/*
* PostScript names indexed by Machintosh as used in TTF 'post' table format 1,
* 2, 2.5.
*/
/* gMacGlyphName has been move to a resource. */
/*
* size of the standard Mac-GlyphName table
*/
#define MAX_MACINDEX 258
/*
* Read Format 0 Subtable : Byte encoding table
*/
unsigned long ReadCMapFormat0(
UFOStruct *pUFO,
unsigned long dwOffset,
long code
)
{
unsigned long gi, dwSize, dwGlyphIDOffset;
unsigned short length;
unsigned short wData[4]; /* read max 4 bytes each time */
unsigned char cData[2]; /* read max 2 bytes each time */
gi = 0 ; /* Assume it's missing. */
dwSize = GETTTFONTDATA(pUFO,
CMAP_TABLE, dwOffset,
wData, 4L,
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return 0;
length = MOTOROLAINT(wData[1]);
if ((code > 0xFF) || (code > ((long) length - 6)))
return 0; /* code is out of range! */
dwGlyphIDOffset = dwOffset + 6 + code ;
dwSize = GETTTFONTDATA(pUFO,
CMAP_TABLE, dwGlyphIDOffset,
cData, 2L,
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return 0;
gi = (unsigned long)(cData[0]);
return gi;
}
/*
* Read Format 2 Subtable : High-byte mapping through table
*/
unsigned long ReadCMapFormat2(
UFOStruct *pUFO,
unsigned long dwOffset,
long code
)
{
unsigned long gi, dwSize, dwGlyphIDOffset;
unsigned short firstCode, entryCount, idRangeOffset;
short subHeaderIndex, idDelta;
unsigned short hiByte, loByte;
unsigned short wData[10]; /* Read max 20 bytes each time. */
gi = 0 ; /* Assume it's missing. */
if (code < 0x100)
{
/* Special: use SubHeader 0. */
loByte = (short) code; // Fixed bug 367732
hiByte = 0;
subHeaderIndex = -1; /* So 8 + subHeaderIndex*8 =0 ==> SunHeader 0... */
}
else
{
loByte = (short) GET_LOBYTE(code);
hiByte = (short) GET_HIBYTE(code);
/* Get the subHeaderIndex from subHeaderKeys[hiByte]. */
dwSize = GETTTFONTDATA(pUFO,
CMAP_TABLE, dwOffset + 6 + 2 * hiByte,
wData, 2L,
pUFO->pFData->fontIndex);
subHeaderIndex = MOTOROLAINT(wData[0]) / 8;
}
dwSize = GETTTFONTDATA(pUFO,
CMAP_TABLE, dwOffset + 6 + 2 * 256 + 8 + subHeaderIndex * 8,
wData, 8L,
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return 0;
firstCode = MOTOROLAINT(wData[0]);
entryCount = MOTOROLAINT(wData[1]);
idDelta = (short)MOTOROLAINT(wData[2]);
idRangeOffset = MOTOROLAINT(wData[3]);
if ((loByte >= firstCode) && ((loByte-firstCode) <= entryCount))
{
/*
* The document says:
* "The value of the idRangeOffset is the number of bytes past the
* actual location of the idRangeOffset word where the glyphIndexArray
* element corresponding to firstCode appears."
*/
dwGlyphIDOffset = dwOffset + 6 + 2 * 256 + 8 + subHeaderIndex * 8
+ 8 + idRangeOffset + (loByte - firstCode) * 2;
dwSize = GETTTFONTDATA(pUFO,
CMAP_TABLE, dwGlyphIDOffset,
wData, 2L,
pUFO->pFData->fontIndex);
gi = MOTOROLAINT(wData[0]);
if (gi != 0)
gi = (unsigned long)((long)gi + (long)idDelta);
}
else
gi = 0;
return gi;
}
/*
* Read format 4 cmap : Segment mapping to delta values
*/
unsigned long ReadCMapFormat4(
UFOStruct *pUFO,
unsigned long dwOffset,
long code
)
{
/*
* These numbers start from the current SubTable for current segment i and
* TotalSeg = segs.
*/
#define OFFSET_ENDCOUNT(segs, i) (long)(14 +((long)i) * 2)
#define OFFSET_STARTCOUNT(segs,i) (long)(14 + ((long)segs) * 2 + 2 + ((long)i) * 2)
#define OFFSET_IDDELTA(segs, i) (long)(14 + ((long)segs) * 2 + 2 + ((long)segs) * 2 \
+ ((long)i) * 2)
#define OFFSET_IDRANGE(segs, i) (long)(14 + ((long)segs) * 2 + 2 + ((long)segs) * 2 \
+ ((long)segs) * 2 + ((long)i) * 2)
unsigned long gi, dwSize, dwGlyphIDOffset;
unsigned short segStartCode, segEndCode, segRangeOffset, nSegments, wData[10], i;
short segDelta;
/*
* Read number of Segments.
*/
dwSize = GETTTFONTDATA(pUFO,
CMAP_TABLE, dwOffset + 6,
wData, 2L,
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return 0;
nSegments = MOTOROLAINT(wData[0]) / 2;
gi = 0; /* Assume it's missing. */
for (i = 0; i < nSegments; i++)
{
/*
* Find the least segEndCode >= code.
*/
dwSize = GETTTFONTDATA(pUFO,
CMAP_TABLE, dwOffset + OFFSET_ENDCOUNT(nSegments, i),
wData, 2L, /* Read 2 bytes = endCount[segCount] */
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
break; /* No more endCount[i] */
segEndCode = MOTOROLAINT(wData[0]);
if (segEndCode == 0xFFFFL)
break; /* No more endCount[i]. 0xFFFF is the end mark. */
if ((long)segEndCode < code)
continue; /* Not in this segment. Move to the next. */
/*
* The code may be in this segment. Get the start code and make sure
* of it.
*/
dwSize = GETTTFONTDATA(pUFO,
CMAP_TABLE, dwOffset + OFFSET_STARTCOUNT(nSegments, i),
wData, 2L,
pUFO->pFData->fontIndex);
if (dwSize == 0)
{
/*
* Something is wrong. Ignore this segment and move to the next.
*/
continue;
}
segStartCode = MOTOROLAINT(wData[0]);
if ((long)segStartCode <= code)
{
/*
* The code is in this segment. Get the idDelta and idRangeOffset.
*/
dwSize = GETTTFONTDATA(pUFO,
CMAP_TABLE, dwOffset + OFFSET_IDDELTA(nSegments, i),
wData, 2L,
pUFO->pFData->fontIndex);
segDelta = (short)MOTOROLAINT(wData[0]); /* mode 65536 */
dwSize = GETTTFONTDATA(pUFO,
CMAP_TABLE, dwOffset + OFFSET_IDRANGE(nSegments, i),
wData, 2L,
pUFO->pFData->fontIndex);
segRangeOffset = MOTOROLAINT(wData[0]);
if (segRangeOffset != 0)
{
dwGlyphIDOffset = dwOffset
+ OFFSET_IDRANGE(nSegments, i)
+ (code - segStartCode) * 2
+ segRangeOffset; /* obscure indexing trick */
dwSize = GETTTFONTDATA(pUFO,
CMAP_TABLE, dwGlyphIDOffset,
wData, 2L,
pUFO->pFData->fontIndex);
gi = MOTOROLAINT(wData[0]);
if (gi != 0)
gi = (unsigned long)((long)gi + (long)segDelta);
}
else
gi = (unsigned long)((long)code + (long)segDelta);
gi %= 65536;
/*
* We got it, so break from this FOR loop and return to the
* caller.
*/
break;
}
}
return gi;
}
/*
* Read Format 6: Trimmed table mapping
*/
unsigned long ReadCMapFormat6(
UFOStruct *pUFO,
unsigned long dwOffset,
long code
)
{
unsigned long gi, dwSize, dwGlyphIDOffset;
unsigned short firstCode, entryCount;
unsigned short wData[10]; /* Read max 20 bytes each time. */
gi = 0; /* Assume it's missing. */
dwSize = GETTTFONTDATA(pUFO,
CMAP_TABLE, dwOffset,
wData, 10L, /* Format 6 header */
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return 0; /* No header */
firstCode = MOTOROLAINT(wData[3]);
entryCount = MOTOROLAINT(wData[4]);
if ((code >= (long)firstCode) && ((code - (long)firstCode) <= (long)entryCount))
{
dwGlyphIDOffset = dwOffset + 10 + (code-firstCode) * 2;
dwSize = GETTTFONTDATA(pUFO,
CMAP_TABLE, dwGlyphIDOffset,
wData, 2L,
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return 0;
gi = MOTOROLAINT(wData[0]);
}
return gi;
}
unsigned long
GetGlyphID(
UFOStruct *pUFO,
long unicode,
long localcode
)
{
unsigned long gi;
gi = GetGlyphIDEx(pUFO,
unicode, localcode,
nil, nil,
GGIEX_HINT_INIT_AND_GET);
return gi;
}
/*
******************************************************************************
* GetGlyphIDEx
*
* How to use this function
*
* You first call this function with hint GGIEX_HINT_INIT and without any
* Unicode and local code info. On return the function gives the caller the
* sub table number and the offset to the table. Then you call this function
* any times you want with hint GGIEX_HINT_GET and Unicode and local code and
* supplied sub table number and the offset. Or, you can call this function
* with hint GGIEX_HINT_INIT_AND_GET and Unicode and local code, which is
* defined as the GetGlyphID function for convenience. The differece of the
* calls with hint GGIEX_HINT_INIT then GGIEX_HINT_GET and the call with hint
* GGIEX_HINT_INIT_AND_GET is that the former is efficent than the latter if
* you need to get multiple glyph IDs. Note that when you call this function
* with hint GGIEX_HINT_INIT then GGIEX_HINT_GET, you *MUST* supply the same
* UFO object through the calls.
*
* This function takes a unicode and a local code and returns the Glyph-Index
* for that unicode if UNICODE-Cmap subtable is found for that local code else.
* As an example, "period-like symbol" Japanese half-width katakana has unicode
* FF61 and (Win/Mac) Shift-JIS local code "0x00A1". An TTF file may contain
* only Shift-JIS based cmap, so we can still get the GID from "0xA1".
* We prefer to use the Unicode cmap-sub table, then the local ones as defined
* in the array preSubTable[].
*
* Here is eight possible PlatformID/EncodingID combinations in our preferred
* order (for Windows).
*
* 3 1 Unicode : Primary one
* 3 2 ShiftJIS
* 3 3 Big5
* 3 4 PRC
* 3 5 Wansung
* 3 6 Johab
* 3 0 Symbol : Don't care much
* 1 0 Mac standard
*
******************************************************************************/
#define CMAP_UNICODE 0
#define CMAP_SHIFTJIS 1
#define CMAP_BIG5 2
#define CMAP_PRC 3
#define CMAP_WANSUNG 4
#define CMAP_JOHAB 5
#define CMAP_SYMBOL 6
#define CMAP_MAC 7
#define CMAP_NUM_ENC 8
static short preSubTable[CMAP_NUM_ENC] = {
CMAP_UNICODE,
CMAP_SHIFTJIS,
CMAP_BIG5,
CMAP_PRC,
CMAP_WANSUNG,
CMAP_JOHAB,
CMAP_SYMBOL,
CMAP_MAC,
};
/* PlatformID 3/EncodingID x to CMapID */
static short pfID3EncIDTable[CMAP_NUM_ENC - 1] = {
/* Encoding ID */
CMAP_SYMBOL, /* 0 */
CMAP_UNICODE, /* 1 */
CMAP_SHIFTJIS, /* 2 */
CMAP_BIG5, /* 3 */
CMAP_PRC, /* 4 */
CMAP_WANSUNG, /* 5 */
CMAP_JOHAB, /* 6 */
};
unsigned long
GetGlyphIDEx(
UFOStruct *pUFO,
long unicode,
long localcode,
short *pSubTable,
unsigned long *pOffset,
int hint
)
{
short subTable;
unsigned long offset;
unsigned long gi;
unsigned long dwSize;
unsigned short version, numEncodings, platformID, encodingID, format, i;
unsigned long lData[20];
unsigned short wData[20]; /* Only first 10 bytes of 'cmap' table required. */
unsigned long dwOffset[CMAP_NUM_ENC]; /* offset to #CMAP_NUM_ENC possible subtables */
if (hint != GGIEX_HINT_GET)
{
/*
* Be sure hint is either GGIEX_HINT_INIT or GGIEX_HINT_INIT_AND_GET.
*/
subTable = -1;
offset = 0;
if (pSubTable)
*pSubTable = subTable;
if (pOffset)
*pOffset = offset;
/*
* First 4 bytes in 'cmap' table has the platform and format information
* unsigned short Table version number (0).
* unsigned short Number of encoding tables, n.
*/
dwSize = GETTTFONTDATA(pUFO,
CMAP_TABLE, 0L,
wData, 4L,
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return 0;
version = MOTOROLAINT(wData[0]);
if (version != 0)
return 0; /* We support only version zero currently. */
for (i = 0; i < CMAP_NUM_ENC; i++)
dwOffset[i] = 0;
numEncodings = MOTOROLAINT(wData[1]);
for (i = 0; i < numEncodings; i++)
{
GETTTFONTDATA(pUFO,
CMAP_TABLE, i * 8 + 4,
wData, 8L,
pUFO->pFData->fontIndex);
platformID = MOTOROLAINT(wData[0]);
encodingID = MOTOROLAINT(wData[1]);
if (platformID == 3)
{
if ((encodingID >= 0) && (encodingID <= 6))
{
GETTTFONTDATA(pUFO,
CMAP_TABLE, i * 8 + 4,
lData, 8L,
pUFO->pFData->fontIndex);
dwOffset[pfID3EncIDTable[encodingID]] = MOTOROLALONG(lData[1]);
}
}
if (platformID == 1)
{
if (encodingID == 0)
{
GETTTFONTDATA(pUFO,
CMAP_TABLE, i * 8 + 4,
lData, 8L,
pUFO->pFData->fontIndex);
dwOffset[CMAP_MAC] = MOTOROLALONG(lData[1]); /* 7 is for Mac Standard. */
}
}
}
/*
* Get the preferred SubTable and its offset based on the preference
* array.
*/
for (i = 0; i < CMAP_NUM_ENC; i++)
{
if (dwOffset[preSubTable[i]] > 0 && dwOffset[preSubTable[i]] < 0xFFFFFFFFL)
{
subTable = preSubTable[i];
offset = dwOffset[subTable];
break;
}
}
}
else
{
/*
* GGIEX_HINT_GET
*/
subTable = pSubTable ? *pSubTable : -1;
offset = pOffset ? *pOffset : 0;
}
if (hint == GGIEX_HINT_INIT)
{
if (pSubTable)
*pSubTable = subTable;
if (pOffset)
*pOffset = offset;
return 0;
}
/*
* The following code is executed when the hint is either GGIEX_HINT_GET
* or GGIEX_HINT_INIT_AND_GET.
*/
gi = 0;
if (0 <= subTable)
{
long code = (subTable == CMAP_UNICODE) ? unicode : localcode;
/*
* Determine if the format of the encoding is one we can handle.
*/
GETTTFONTDATA(pUFO,
CMAP_TABLE, offset,
wData, 8L,
pUFO->pFData->fontIndex);
format = MOTOROLAINT(wData[0]);
switch (format)
{
case 4:
/*
* Format 4: Segment mapping to delta values (MS standard format)
* Get the glyphID using unicode or localcode.
*/
gi = ReadCMapFormat4(pUFO, offset, code);
break;
case 0:
/*
* Format 0: Byte encoding table
* Only used for small fonts - or only first 256 chars accessible.
* We really don't care for this guy for CJK, but for completeness.
*/
gi = ReadCMapFormat0(pUFO, offset, code);
break;
case 2:
/*
* Format 2: High-byte mapping through table
* THIS format SHOULD use localcode - because the sigle byte chars
* are in the subHeader 0. But some font may mess up the standard
* as always.
*/
gi = ReadCMapFormat2(pUFO, offset, code);
break;
case 6:
/*
* Format 6: Trimmed table mapping
* Get the glyphID using unicode or localcode.
*/
gi = ReadCMapFormat6(pUFO, offset, code);
break;
default:
break;
}
}
return(gi);
}
/*
******************************************************************************
'vmtx' table
- Vertical Metrics Table Format -
The overall structure of the vertical metrics table consists of two arrays
shown below:
the vMetrics array followed by an array of top side bearings. This table does
not have a header, but does require that the number of glyphs included in the
two arrays equals the total number of glyphs in the font. The number of
entries in the vMetrics array is determined by the value of the
numOfLongVerMetrics field of the vertical header table. The vMetrics array
contains two values for each entry. These are the advance height and the top
sidebearing for each glyph included in the array. In monospaced fonts, such as
Courier or Kanji, all glyphs have the same advance height. If the font is
monospaced, only one entry need be in the first array, but that one entry is
required. The format of an entry in the vertical metrics array is given below.
Type Name Description
USHORT advanceHeight The advance height of the glyph. Unsigned integer
in FUnits
SHORT topSideBearing The top sidebearing of the glyph. Signed integer
in FUnits.
The second array is optional and generally is used for a run of monospaced
glyphs in the font. Only one such run is allowed per font, and it must be
located at the end of the font. This array contains the top sidebearings of
glyphs not represented in the first array, and all the glyphs in this array
must have the same advance height as the last entry in the vMetrics array. All
entries in this array are therefore monospaced. The number of entries in this
array is calculated by subtracting the value of numOfLongVerMetrics from the
number of glyphs in the font. The sum of glyphs represented in the first array
plus the glyphs represented in the second array therefore equals the number of
glyphs in the font. The format of the top sidebearing array is given below.
Type Name Description
SHORT topSideBearing[] The top sidebearing of the glyph. Signed
integer in FUnits.
*******************************************************************************/
/*
** Old comment
** GetCharWidthFromTTF was replaced to GetMetrics2FromTTF in order to fix
** #277035 and #277063. (See old history of this code in SourceSafe to see
** what GetCharWidthFromTTF code was doing.)
** More old comment
** Modified this procedure to fix bug 287084. Bug fix 277035 and 277063 works
** for NT but not for W95. See vantive report for 287084.
*/
/*
* New comment
*
* Table search order for vertical metrics on Windows.
*
* 1. First look for 'vhea' table (only on NT).
* 2. If 'vhea' table is missing, look for 'OS/2' table.
* 3. If 'OS/2' table is missing neither, then look for 'hhea' table.
*
* When 'OS/2' or 'hhea' table is found, Windows uses its horizontal ascender
* and descender values as vertical's. Note that according to Microsoft Win 9x
* doesn't care of 'vhea' table.
*
* In the code below we look for the tables differently: look for 'OS/2' table
* first, then 'hhea' table. Then we look for 'vhea' on NT but ignore it on 9x.
* Although we ignore 'vhea' table on 9x, we still use metrics in 'vmtx' table
* on both NT and 9x.
*/
UFLErrCode
GetMetrics2FromTTF(
UFOStruct *pUFO,
unsigned short gi,
long *pem,
long *pw1y,
long *pvx,
long *pvy,
long *ptsb,
UFLBool *bUseDef,
UFLBool bGetDefault,
long *pvasc
)
{
unsigned short wData[48]; /* 'hhea' and 'vhea' are 36 bytes long. 'OS/2 is either 78 or 86 bytes. */
unsigned long dwSize, dwOffset;
long em, lAscent, lDescent, lNumLongVM, AdvanceHeight, lAscent2, lDescent2;
UFLBool bSkiphhea = 1;
/*
* Get EM of this font. Getting first 22 bytes from 'head' table is enough.
*/
dwSize = GETTTFONTDATA(pUFO,
HEAD_TABLE, 0L,
wData, 22L,
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
{
/*
* 'head' is a required table so that em has to be avaiable. This is
* merely divide by 0 proof, wild guess value.
*/
em = 256;
}
else
{
/* 9th unsigned short is the font design unit. */
em = (long)MOTOROLAINT(wData[9]);
}
*pem = em;
/*
* Get vx and vy, descent and ascent, of Metrics2.
*
* WCC - Bug 303030 - For Win9x, we want to try 'OS/2' table first, then
* 'vhea' table. Refer to #287084 too for additional info.
*
* We don't care of ulCodePageRange values added at the end of version 1 of
* 'OS/2' table so that specify version 0's length 78 instead of 86. This
* prevents to failure of 'OS/2' table access.
*/
dwSize = GETTTFONTDATA(pUFO,
OS2_TABLE, 0L,
wData, 78L,
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
{
bSkiphhea = 0; /* Failed to get info from 'OS/2' table. Use 'hhea' table then. */
}
else
{
/*
* Our investigation shows that 9x and NT/W2K use different ascender
* and descender values in 'OS/2' table. 9x uses sTypoAscender and
* sTypoDescender values. On the other hand, NT4 and W2K use
* usWinAscent and usWinDescent. There are acutally some CJK TrueType
* fonts which have different sTypoAscender/Descender and
* usWinAscent/Descent values.
*
* Note that this function is also called to get metrics data for
* OpenType font to fix bug #366539, and the fix revealed that we
* need to use sTypoAscender/descender values from 'OS/2' table.
*/
if ((pUFO->vpfinfo.nPlatformID == kUFLVPFPlatformID9x) || (pUFO->ufoType == UFO_CFF))
{
lAscent = (long)MOTOROLASINT(wData[34]); /* sTypoAscender */
lDescent = (long)MOTOROLASINT(wData[35]); /* sTypoDescender */
}
else /* TTF and NT4/W2K */
{
lAscent = (long)MOTOROLASINT(wData[37]); /* usWinAscent */
lDescent = (long)MOTOROLASINT(wData[38]); /* usWinDecent */
}
if (lDescent < 0)
lDescent = -lDescent;
}
dwSize = GETTTFONTDATA(pUFO,
HHEA_TABLE, 0L,
wData, 36L,
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
{
/*
* Talisman - 'hhea' is a required table.
*/
lDescent2 = (long)em / 8; /* This is a wild guess value. */
lAscent2 = (long)(em - lDescent2);
}
else
{
lAscent2 = (long)MOTOROLASINT(wData[2]);
lDescent2 = (long)MOTOROLASINT(wData[3]);
if (lDescent2 < 0)
lDescent2 = -lDescent2;
}
if (!bSkiphhea)
{
/* Failed to get ascent and descent values from 'OS/2' table, so use these. */
lAscent = lAscent2;
lDescent = lDescent2;
}
/*
* Up to here we got initial default values.
*/
*bUseDef = 1;
*pvx = lDescent;
*pvy = lAscent;
*pw1y = em;
*ptsb = 0;
/*
* Win 9x doesn't care of 'vhea' and so are NT/W2K (see bug #316067 and
* #277035). But we get ascender value of 'vhea' anyway in order to adjust
* the 'full-width glyph layout policy' difference between GDI and
* %hostfont%-RIP (#384736).
*/
dwSize = GETTTFONTDATA(pUFO,
VHEA_TABLE, 0L,
wData, 36L,
pUFO->pFData->fontIndex);
if ((dwSize != 0) && (dwSize != 0xFFFFFFFFL))
{
lAscent2 = (long)MOTOROLASINT(wData[2]);
}
else
{
/*
* When the font doesn't have 'vhea', we need to adjust the policy
* difference in a different way; using 'GDI' CDevProc instead of
* adjusted matrix. To cause that, return to the caller with same
* vy and vasc values.
*/
lAscent2 = lAscent;
/*
* Without 'vhea' table 'vmtx' table doesn't make sense.
* Return as though only default values are requested.
*/
bGetDefault = 1;
}
*pvasc = lAscent2;
/*
* Return when only default values are required.
*/
if (bGetDefault)
return kNoErr;
/*
* Get AdvanceHeight and TopSideBearing of each glyph from 'vmtx' table.
*/
lNumLongVM = (long)MOTOROLAINT(wData[17]); // From 'vhea' table
if ((!bGetDefault) && ((long) gi < lNumLongVM))
{
/*
* gi is in the 1st array: each entry is 4 bytes long.
*/
dwOffset = 4 * ((unsigned long)gi);
dwSize = GETTTFONTDATA(pUFO,
VMTX_TABLE, dwOffset,
wData, 4L,
pUFO->pFData->fontIndex);
if ((dwSize != 0) && (dwSize != 0xFFFFFFFFL))
{
*pw1y = (long)MOTOROLAINT(wData[0]); /* AdvanceHeight */
*ptsb = (long)MOTOROLASINT(wData[1]); /* TopSideBearing */
*bUseDef = 0;
}
}
else
{
/*
* gi is in the 2nd array: find width from the last entry in the 1st
* array first, then TopSideBearing in the 2nd array.
*/
dwOffset = 4 * (lNumLongVM - 1);
dwSize = GETTTFONTDATA(pUFO,
VMTX_TABLE, dwOffset,
wData, 4L,
pUFO->pFData->fontIndex);
if ((dwSize != 0) && (dwSize != 0xFFFFFFFFL))
{
AdvanceHeight = (long)MOTOROLAINT(wData[0]);
dwOffset = (4 * lNumLongVM) + (2 * (gi - lNumLongVM));
dwSize = GETTTFONTDATA(pUFO,
VMTX_TABLE, dwOffset,
wData, 2L,
pUFO->pFData->fontIndex);
if ((dwSize != 0) && (dwSize != 0xFFFFFFFFL))
{
*pw1y = AdvanceHeight;
*ptsb = (long)MOTOROLASINT(wData[0]); /* TopSideBearing */
*bUseDef = 0;
}
}
}
return kNoErr;
}
unsigned long
GetNumGlyphs(
UFOStruct *pUFO
)
{
MaxPTableStruct MaxPTable;
unsigned long dwSize;
/* Get the size of the 'maxp' table. */
dwSize = GETTTFONTDATA(pUFO,
MAXP_TABLE, 0L,
nil, 0L,
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return 0;
// Fixed 516508. case 1
if (dwSize > sizeof(MaxPTable))
dwSize = sizeof(MaxPTable);
dwSize = GETTTFONTDATA(pUFO,
MAXP_TABLE, 0L,
&MaxPTable, dwSize,
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return 0;
return MOTOROLAINT(MaxPTable.numGlyphs);;
}
/*
* Returns the fsType value from the OS/2 table. If the OS/2 table isn't
* defined then -1 is returned.
*/
long GetOS2FSType(UFOStruct *pUFO)
{
UFLOS2Table os2Tbl;
unsigned long dwSize;
dwSize = GETTTFONTDATA(pUFO,
OS2_TABLE, 0L,
&os2Tbl, sizeof (UFLOS2Table),
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return -1;
return MOTOROLAINT(os2Tbl.fsType);
}
/*
* TTC File related functions
*/
UFLBool
BIsTTCFont(
unsigned long ulTag
)
{
return (ulTag == TTCF_TABLE);
}
unsigned short
GetFontIndexInTTC(
UFOStruct *pUFO
)
/*++
Routine Description:
Find the fontIndex from pUFO->UniqueNameA/W. The return value is the font
index or FONTINDEX_UNKNOWN.
--*/
{
TTCFHEADER ttcfHeader;
unsigned long dwSize;
unsigned short i, j, k, sTemp;
unsigned long lData;
unsigned short wData[3];
unsigned long offsetToTableDir;
unsigned long ulOffsetToName, ulLengthName;
unsigned long cNumFonts;
unsigned short cNumNameRecords;
unsigned short fontIndex;
NAMERECORD *pNameRecord = nil;
unsigned char *pName = nil;
dwSize = GETTTFONTDATA(pUFO,
nil, 0L,
&ttcfHeader, sizeof (ttcfHeader),
0);
if (!BIsTTCFont(*((unsigned long *)((char *)&ttcfHeader))))
{
/* This is not a TTC file, so return font index 0. */
return 0;
}
fontIndex = FONTINDEX_UNKNOWN;
dwSize = sizeof (NAMERECORD);
pNameRecord = (NAMERECORD *)UFLNewPtr(pUFO->pMem, dwSize);
if (pNameRecord == nil)
return fontIndex;
cNumFonts = (unsigned long)MOTOROLALONG(ttcfHeader.cDirectory);
for (i = 0; i < cNumFonts; i++)
{
/*
* Get offset to the ith tableDir first: a long at 4 * i right after
* ttcfHeader.
*/
dwSize = GETTTFONTDATA(pUFO,
nil, sizeof (ttcfHeader) + i * 4,
&lData, sizeof (lData),
0);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
continue;
offsetToTableDir = MOTOROLALONG(lData);
/*
* Get 'name' table record for i-th font in this TTC. Find number of
* NameRecords and offset to String storage: use 3 shorts.
*/
dwSize = GETTTFONTDATA(pUFO,
NAME_TABLE, 0L,
wData, 3 * sizeof (short),
i);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
continue;
cNumNameRecords = MOTOROLAINT(wData[1]);
ulOffsetToName = (unsigned long)MOTOROLAINT(wData[2]);
/*
* Look into the NameRecords: Search for both platform: MS-Platform,
* Mac-Platform.
*/
for (k = 0; k < cNumNameRecords; k++)
{
dwSize = GETTTFONTDATA(pUFO,
NAME_TABLE, 3 * sizeof (short) + k * sizeof (NAMERECORD),
pNameRecord, sizeof (NAMERECORD),
i);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
continue;
/* We are looking for particular NameID record. */
if (MOTOROLAINT(pNameRecord->nameID) != NAMEID_FACENAME)
continue;
/* We only read MS or Mac Platform. */
if ((MOTOROLAINT(pNameRecord->platformID) != MS_PLATFORM)
&& (MOTOROLAINT(pNameRecord->platformID) != MAC_PLATFORM))
continue;
/* Get the "unique identifier" string. */
ulLengthName = MOTOROLAINT(pNameRecord->length);
/*
* This is in a loop, so pName maybe allocated already.
* Free it first.
*/
if (pName)
{
UFLDeletePtr(pUFO->pMem, pName);
pName = nil;
}
dwSize = ulLengthName + 4 ; // add two 00 at the end.
pName = (unsigned char *)UFLNewPtr(pUFO->pMem, dwSize);
if (pName == nil)
{
/* Allocation failed. */
break;
}
dwSize = GETTTFONTDATA(pUFO,
NAME_TABLE, ulOffsetToName + MOTOROLAINT(pNameRecord->offset),
pName, ulLengthName,
i);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
continue;
/*
* Note that OS/2 and Windows both require that all name strings
* be defined in Unicode. !!!BUT!!! Macintosh fonts require single
* byte strings!
*/
if ((MOTOROLAINT(pNameRecord->platformID) == MS_PLATFORM)
&& pUFO->pFData->pUniqueNameW)
{
/*
* For Windows EncodingID must be 0 or 1: both are in Unicode.
* So, do Unicode comparison - pUniqueNameW is not in Motorola
* format on Windows. So Convert pName to Motorola format.
*/
j = 0;
while (sTemp = *(((unsigned short *)pName) + j), sTemp != 0)
{
*(((unsigned short *)pName) + j) = MOTOROLAINT(sTemp);
j++;
}
if (UFLstrcmpW((unsigned short *)(pUFO->pFData->pUniqueNameW),
(unsigned short *)pName) == 0)
{
fontIndex = i;
break;
}
}
if ((MOTOROLAINT(pNameRecord->platformID) == MAC_PLATFORM)
&& pUFO->pFData->pUniqueNameA)
{
/* Do single Byte-string comparison. */
if (UFLstrcmp(pUFO->pFData->pUniqueNameA, (char *)pName) == 0)
{
fontIndex = i;
break;
}
}
} /* for k from 0 to numRecords in this font's name table */
/* If find one, break out of the loop. */
if (fontIndex != FONTINDEX_UNKNOWN)
break;
} /* for i = 0 to numFonts */
if (pName != nil)
UFLDeletePtr(pUFO->pMem, pName);
if (pNameRecord != nil)
UFLDeletePtr(pUFO->pMem, pNameRecord);
return fontIndex;
}
unsigned long
GetOffsetToTableDirInTTC(
UFOStruct *pUFO,
unsigned short fontIndex
)
{
unsigned long dwSize;
TTCFHEADER ttcfHeader;
unsigned long lData;
unsigned long offsetToTableDir;
dwSize = GETTTFONTDATA(pUFO,
nil, 0L,
&ttcfHeader, sizeof (ttcfHeader),
0);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return 0;
if (!BIsTTCFont( *((unsigned long *)((char *)&ttcfHeader))))
{
/* Not TTC file: offsetToTableDir is at 0. */
return 0;
}
/*
* Get offset to the tableDir: a long at 4 * FontIndex right after
* ttcfHeader.
*/
dwSize = GETTTFONTDATA(pUFO,
nil, sizeof (ttcfHeader) + fontIndex * 4,
&lData, sizeof (lData),
0);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return 0;
offsetToTableDir = MOTOROLALONG(lData);
return offsetToTableDir;
}
char *
GetGlyphName(
UFOStruct *pUFO,
unsigned long lGid,
char *pszHint,
UFLBool *bGoodName /* GoodName */
)
/*++
Routine Description:
Function to parse 'post' table to figure out PostScript name for Glyph
lGid.
IF found a name
return the pointer to name (NULL terminated)
ELSE
return the passed in pszHint
Note: The returned pointer is Global, either gMacGlyphName[x] or gGlyphName.
--*/
{
POSTHEADER *ppostHeader;
unsigned long dwSize, dwNumGlyph, j;
char *pszName;
char cOffset;
long newIndex = 0, lOffset;
short i;
unsigned short sIndex = 0;
unsigned char *pUSChar;
unsigned short *pUSShort;
unsigned long dwNumGlyphInPostTb;
char **gMacGlyphNames;
// Fixed bug #516515
char *gGlyphName;
gGlyphName = pUFO->pAFont->gGlyphName;
*bGoodName = 0; /* GoodName */
gMacGlyphNames = (char **)(pUFO->pMacGlyphNameList);
/*
* Initialize to a reasonable name.
*/
if ((pszHint == nil) || (*pszHint == '\0'))
{
// UFLsprintf(gGlyphName, "G%x", lGid);
UFLsprintf(gGlyphName, CCHOF(pUFO->pAFont->gGlyphName), "g%d", lGid);
pszName = gGlyphName;
}
else
pszName = pszHint;
if (pUFO->lNumNT4SymGlyphs)
return pszName;
/* GoodName */
if (lGid == 0)
{
UFLsprintf(gGlyphName, CCHOF(pUFO->pAFont->gGlyphName), ".notdef");
*bGoodName = 1;
return gGlyphName;
}
/*
* For Speed, we save the postTable now - about 5K of data per font.
*/
if (pUFO->pAFont->pTTpost == nil)
{
dwSize = GETTTFONTDATA(pUFO,
POST_TABLE, 0L,
nil, 0L,
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return pszName;
pUFO->pAFont->dwTTPostSize = dwSize;
pUFO->pAFont->pTTpost = (void *)UFLNewPtr(pUFO->pMem, dwSize);
if (pUFO->pAFont->pTTpost)
{
dwSize = GETTTFONTDATA(pUFO,
POST_TABLE, 0L,
pUFO->pAFont->pTTpost, dwSize,
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return pszName;
}
else
return pszName;
}
/*
* Get the 'post' table record to figure out the format.
*/
ppostHeader = pUFO->pAFont->pTTpost;
/* A convenient byte pointer */
pUSChar = (unsigned char *)pUFO->pAFont->pTTpost;
pUSShort = (unsigned short *)(pUSChar + sizeof(POSTHEADER));
dwNumGlyphInPostTb = (unsigned long)MOTOROLAINT(*pUSShort);
dwNumGlyph = pUFO->pFData->cNumGlyphs;
if (dwNumGlyph == 0)
dwNumGlyph = GetNumGlyphs(pUFO);
/*
* To protect against bad Glyph-IDs
*/
if (lGid >= dwNumGlyph)
return pszName;
switch (MOTOROLALONG(ppostHeader->format))
{
case POST_FORMAT_10: /* Standard MacIndex fomat */
if (lGid < MAX_MACINDEX )
{
if (gMacGlyphNames)
{
pszName = gMacGlyphNames[lGid];
*bGoodName = 1; /* GoodName */
}
}
break;
case POST_FORMAT_20: /* Mac-Index Plus additional Pascal strings */
if (lGid <= dwNumGlyph)
{
/*
* Use lGid to get the index to the Mac standard names.
*/
lOffset = sizeof (POSTHEADER) + sizeof(short) + sizeof(short) * lGid;
pUSShort = (unsigned short *)(pUSChar + lOffset);
sIndex = pUSShort[0];
sIndex = MOTOROLAINT(sIndex);
if ((sIndex == 0) && (lGid > 0))
{
/*
* Handle specila case. If there is no entry in 'post'
* table for this glyph index, using Glyph ID as the name.
* Fix Adobe Bug 233027.
*/
}
else if (sIndex < MAX_MACINDEX)
{
if (gMacGlyphNames)
{
pszName = gMacGlyphNames[sIndex];
*bGoodName = 1; /* GoodName */
}
}
/*
* Add condition (dwNumGlyphInPostTb == dwNumGlyph) to work around
* the problem in TT font marigold.
*/
else if ((sIndex < 32768) && (dwNumGlyphInPostTb == dwNumGlyph))
{
/* 32768 to 64K is reserved for future use */
newIndex = (long)sIndex - (long)MAX_MACINDEX;
lOffset = sizeof(POSTHEADER) + sizeof(short) + sizeof(short)* dwNumGlyph ;
i = 0;
j = lOffset;
while (j < pUFO->pAFont->dwTTPostSize)
{
cOffset = pUSChar[j];
/*
* Bad 'post' table could have an 0-length pascal string,
* don't stuck here.
*/
if (cOffset == (char)0)
break;
if ((j + (short)((unsigned char) cOffset) + 1) >= pUFO->pAFont->dwTTPostSize)
break;
if (i >= newIndex)
break;
j += (long)((unsigned char)cOffset) + 1;
i++;
}
/*
* Found it.
*/
if (i == newIndex)
{
// For #516515: cOffset is one byte, the buffer size of the
// gGlyphName is 256. So, it is safe to copy here.
UFLmemcpy((const UFLMemObj* )pUFO->pMem,
(void *) gGlyphName,
(void *)(pUSChar + j + 1),
(UFLsize_t)cOffset);
*(gGlyphName + ((unsigned char)cOffset)) = '\0';
pszName = gGlyphName;
*bGoodName = 1; /* GoodName */
}
}
}
break;
#if 0
case POST_FORMAT_25: /* Re-ordered Mac-Index */
/*
* Use lGid to get the index to the Mac standard names.
*/
if (lGid >= MAX_MACINDEX )
break;
cOffset = pUSChar[sizeof(POSTHEADER) + lGid];
/*
* DCR -- confirm format 2.5 with a Mac font.
*/
newIndex = (long)lGid + (long)cOffset;
if ((sIndex == 0) && (lGid > 0))
{
/*
* Handle specila case. If there is no entry in 'post' table for
* this glyph index, using Glyph ID as the name.
* Fix Adobe Bug 233027.
*/
}
else if (newIndex < MAX_MACINDEX )
{
if (gMacGlyphNames)
{
pszName = gMacGlyphNames[newIndex];
*bGoodName = 1; /* GoodName */
}
}
break;
#endif
case POST_FORMAT_30: /* No name at all */
/*
* Do we want to add 'cmap' reverse parsing?
* It would be very expensive!!
*/
break;
default:
break;
}
return pszName;
}
UFLBool
BHasGoodPostTable(
UFOStruct *pUFO
)
/*++
Routine Description:
Function to check if good 'post' table is available or not.
As of to day, only format 1.0, 2.0, 2.5 are considered good - we can get
"good GlyphNames" from it.
--*/
{
POSTHEADER postHeader;
unsigned long dwSize;
long lFormat;
/*
* Get the 'post' table record to figure out the format.
*/
dwSize = GETTTFONTDATA(pUFO,
POST_TABLE, 0L,
&postHeader, sizeof (POSTHEADER),
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return 0;
lFormat = MOTOROLALONG(postHeader.format);
if ((lFormat == POST_FORMAT_10)
|| (lFormat == POST_FORMAT_20)
|| (lFormat == POST_FORMAT_25))
return 1;
return 0;
}
short int
CreateXUIDArray(
UFOStruct *pUFO,
unsigned long *pXuid
)
/*++
Routine Description:
Creates a xuid array in pXuid for this UFO.
It's format is [44 checkSUM]. 44 is a new XUID identifier given by
TDoweling 2/10/99. The checkSUM is a cumulation of all the entry in
TableEntry. We do this to fix bug 287085.
If pXuid is null, return the "number of long"s needed in pXuid pointer.
--*/
{
short int num = 0;
unsigned long ulSum = 0;
/* The first number is 44. */
if (pXuid)
*pXuid = 44;
num++;
if (pXuid)
{
TableDirectoryStruct tableDir;
TableEntryStruct tableEntry;
unsigned long dwSize;
unsigned short int i;
/* Get the TableDirectory from the TTC/TTF file. */
dwSize = GETTTFONTDATA(pUFO,
nil, pUFO->pFData->offsetToTableDir,
&tableDir, sizeof tableDir,
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return 0;
for (i = 0; i < MOTOROLAINT(tableDir.numTables); i++)
{
/*
* Get each TableEntry which are right after Directory in TTC/TTF file.
*/
dwSize = GETTTFONTDATA(pUFO,
nil, pUFO->pFData->offsetToTableDir
+ sizeof (TableDirectoryStruct)
+ (i * sizeof (TableEntryStruct)),
&tableEntry, sizeof tableEntry,
pUFO->pFData->fontIndex);
if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
return 0;
ulSum += (unsigned long)tableEntry.tag;
ulSum += (unsigned long)tableEntry.checkSum;
ulSum += (unsigned long)tableEntry.offset;
ulSum += (unsigned long)tableEntry.length;
}
}
if (pXuid)
*(pXuid + 1) = ulSum;
num++;
return num;
}