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.
 
 
 
 
 
 

1516 lines
47 KiB

/*
* Adobe Universal Font Library
*
* Copyright (c) 1996 Adobe Systems Inc.
* All Rights Reserved
*
* UFOCFF.c - Compact Font Format Object
*
******************************************************************************
*
* Note about SUBSET_PREFIX and more comment for VRT2_FEATURE_DISABLED
*
* When we donwload a font, its /FontName or /CIDFontName can be any name we
* want. If the name folows the following format:
* SUBSET_PREFIX+RealFontName
* where SUBSET_PREFIX is a string consited of six characters, each of them is
* either 'a' ~ 'p' or 'A' ~ 'P', then Distiller4 takes RealFontName part as
* the font's real name. e.g. abcdef+Helvetica -> Distiller4 realizes that this
* this font's real font name is Helvetica.
* We, Adobe Windows Driver Group, decided to go for it (bug #291934). At the
* same time, we also deciced to remve the code for 'vrt2' feature incapable
* CJK OpenType font, that is, remove #ifdef/#endif with VRT2_FEATURE_DISABLED
* because virtually any CJK OpenType fonts are supposed to have 'vrt2'
* feature. Otherwise vertical version of such CJK OpenType font can't be
* supported (by ATM or CoolType). Thus, there will be no #ifdef/#endif section
* with VRT2_FEATURE_DISABLED keyword in this code and the sentence "But, just
* in case, ....at compile time." in the following note is now obsolite.
* You can retrieve the removed code from the version 16 or below of this file
* in SourceSafe if you want.
*
* --- This note is now obsolete. ---------------------------------------------
*
* Note about 'vrt2' feature and VRT2_FEATURE_DISABLED
*
* OTF-based fonts will only have their "@" capability enabled if they have a
* 'vrt2' feature in their 'GSUB' table; otherwise only horizontal typographic
* rendering is enabled. When the 'vrt2' feature exists in a font, the font
* vendor claims that all of the glyphs for the @ variant of the font should be
* rotated before display / print. Thus, on neither NT4 nor W2K, the PostScript
* driver doesn't even have to call GlyhAttrs to find out which @ glyphs are
* rotated; they all are. But, just in case, the logic for rotating @ glyphs is
* also provided and it will be enabled when VRT2_FEATURE_DISABLED flag is set
* at compile time.
*-----------------------------------------------------------------------------
*
* $Header:
*/
#include "UFLMem.h"
#include "UFLErr.h"
#include "UFLPriv.h"
#include "UFLVm.h"
#include "UFLStd.h"
#include "UFLMath.h"
#include "UFLPS.h"
#include "ParseTT.h"
#include "UFOCff.h"
#include "UFOt42.h"
#include "ttformat.h"
#ifdef UNIX
#include <sys/varargs.h>
#include <assert.h>
#else
#ifdef MAC_ENV
#include <assert.h>
#endif
#include <stdarg.h>
#endif
static unsigned char *pSubrNames[4] = {
(unsigned char*) "F0Subr",
(unsigned char*) "F1Subr",
(unsigned char*) "F2Subr",
(unsigned char*) "HSSubr"
};
#define VER_WO_OTHERSUBRS 51
/*
* Maximum known supplement number. This number is used to decide whether
* GlyphName2Unicode table should be downloaded.
*/
#define ADOBE_JAPAN1_MAXKNOWN 4
#define ADOBE_KOREA1_MAXKNOWN 1
#define ADOBE_GB1_MAXKNOWN 2
#define ADOBE_CNS1_MAXKNOWN 0
/*
* Macro to check whether they are known ordering and supplement.
*/
#define KNOWN_OS(o, on, s, max) (!UFLstrcmp((o), (on)) && ((0 <= (s)) && ((s) < (max))))
/******************************************************************************
*
* Callback Functions
*
******************************************************************************/
static unsigned long int
AllocateMem(
void PTR_PREFIX *PTR_PREFIX *hndl,
unsigned long int size,
void PTR_PREFIX *clientHook
)
{
UFOStruct *pUFO = (UFOStruct *)clientHook;
if ((size == 0) && (*hndl == nil))
return 1;
if (size == 0)
{
UFLDeletePtr(pUFO->pMem, *hndl);
*hndl = nil;
return 1;
}
if (*hndl == nil)
{
*hndl = UFLNewPtr(pUFO->pMem, size);
return (unsigned long int)(ULONG_PTR)*hndl;
}
else
{
return (unsigned long int)UFLEnlargePtr(pUFO->pMem, (void **)hndl, size, 1);
}
return 1;
}
/* We do not support seeking for this function. */
static int
PutBytesAtPos(
unsigned char PTR_PREFIX *pData,
long int position,
unsigned short int length,
void PTR_PREFIX *clientHook
)
{
if (position >= 0)
{
return 0;
}
if (length > 0)
{
UFOStruct *pUFO = (UFOStruct *)clientHook;
if (kNoErr == StrmPutBytes(pUFO->pUFL->hOut,
(const char *)pData,
(UFLsize_t)length,
(const UFLBool)StrmCanOutputBinary(pUFO->pUFL->hOut)))
{
return 0;
}
}
return 1;
}
static int
GetBytesFromPos(
unsigned char PTR_PREFIX * PTR_PREFIX *ppData,
long int position,
unsigned short int length,
void PTR_PREFIX *clientHook
)
{
UFOStruct *pUFO = (UFOStruct *)clientHook;
CFFFontStruct *pFont = (CFFFontStruct *)pUFO->pAFont->hFont;
int retVal = 0; /* Set retVal to failure. */
/*
* Check to see if the client passes us a whole cff table.
*/
if (pFont->info.ppFontData)
{
/*
* Get the data from the table by ourself.
*/
if ((unsigned long int)(position + length) <= pFont->info.fontLength)
{
*ppData = (unsigned char PTR_PREFIX *)*pFont->info.ppFontData + position;
retVal = 1;
}
}
else
{
UFLCFFReadBuf *pReadBuf = pFont->pReadBuf;
if (0 == pReadBuf->cbBuf)
{
pReadBuf->pBuf = (unsigned char PTR_PREFIX *)UFLNewPtr(pUFO->pMem, length);
if (pReadBuf->pBuf)
pReadBuf->cbBuf = length;
else
return 0;
}
else if (pReadBuf->cbBuf < length)
{
UFLEnlargePtr(pUFO->pMem, (void **)&pReadBuf->pBuf, length, 0);
pReadBuf->cbBuf = length;
}
/*
* Fall back to read from callback function.
*/
retVal = (int)GETTTFONTDATA(pUFO,
CFF_TABLE,
position,
pReadBuf->pBuf,
length,
pFont->info.fData.fontIndex);
*ppData = (unsigned char PTR_PREFIX *)pReadBuf->pBuf;
}
return retVal;
}
/******************************************************************************
*
* Private Functions
*
******************************************************************************/
static void *
SetMemory(
void *dest,
int c,
unsigned short int count
)
{
return UFLmemsetShort(dest, c, (size_t) count);
}
static unsigned short int
StringLength(
const char PTR_PREFIX *string
)
{
return (unsigned short int)UFLstrlen(string);
}
static void
MemCpy(
void PTR_PREFIX *dest,
const void PTR_PREFIX *src,
unsigned short int count
)
{
memcpy(dest, (void*)src, (size_t)count);
}
static int
AsciiToInt(
const char* string
)
{
return atoi(string);
}
static long
StringToLong(
const char *nptr,
char **endptr,
int base
)
{
return UFLstrtol(nptr, endptr, base);
}
static int
StrCmp(
const char PTR_PREFIX *string1,
const char PTR_PREFIX *string2
)
{
return UFLstrcmp(string1, string2);
}
static int
GetCharName(
XFhandle handle,
void *client,
XCFGlyphID glyphID,
char PTR_PREFIX *charName,
unsigned short int length
)
{
if (client)
{
/*
* Copy the charname by ourself because the name string returned from
* XCF is not NULL terminated.
*/
unsigned short int i;
/* UFLsprintf((char*)client, "%s", charName); */
for (i = 0; i < length; i++)
*((char *)client)++ = *charName++;
*((char *)client) = '\0';
return XCF_Ok;
}
return XCF_InternalError;
}
static int
GIDToCID(
XFhandle handle,
void PTR_PREFIX *client,
XCFGlyphID glyphID,
unsigned short int cid
)
{
if (client)
{
unsigned short int *pCid = (unsigned short int *)client;
*pCid = cid;
return XCF_Ok;
}
return XCF_InternalError;
}
static void
getFSType(
XFhandle h,
long PTR_PREFIX *pfsType,
void PTR_PREFIX *clientHook
)
{
UFOStruct* pUFO;
long fsType;
if (!pfsType)
return;
*pfsType = -1; /* "Don't put FSType" by default. */
if (!(pUFO = (UFOStruct*)clientHook))
return;
fsType = GetOS2FSType(pUFO);
if(0 <= fsType)
*pfsType = fsType;
}
/* GOODNAME */
static void
isKnownROS(XFhandle h,
long PTR_PREFIX *pknownROS,
char PTR_PREFIX *R,
Card16 lenR,
char PTR_PREFIX *O,
Card16 lenO,
long S,
void PTR_PREFIX *clientHook
)
{
UFOStruct *pUFO;
if (!pknownROS)
return;
*pknownROS = 0;
if (!(pUFO = (UFOStruct*)clientHook))
return;
if ((lenR < 32) && (lenO < 32))
{
char Registry[32], Ordering[32];
int i;
for (i = 0; i < (int) lenR; i++)
Registry[i] = (char) R[i];
Registry[lenR] = '\0';
for (i = 0; i < (int)lenO; i++)
Ordering[i] = (char) O[i];
Ordering[lenO] = '\0';
if (!UFLstrcmp(Registry, "Adobe"))
{
if ( KNOWN_OS(Ordering, "Japan1", S, ADOBE_JAPAN1_MAXKNOWN)
|| KNOWN_OS(Ordering, "Korea1", S, ADOBE_KOREA1_MAXKNOWN)
|| KNOWN_OS(Ordering, "GB1", S, ADOBE_GB1_MAXKNOWN )
|| KNOWN_OS(Ordering, "CNS1", S, ADOBE_CNS1_MAXKNOWN ))
{
*pknownROS = 1;
}
}
}
if (*pknownROS)
pUFO->pAFont->knownROS = 1;
else
{
pUFO->pAFont->knownROS = 0;
pUFO->dwFlags |= UFO_HasG2UDict;
}
}
int
printfError(
const char *format, ...
)
{
va_list arglist;
int retval = 0;
char buf[512];
va_start(arglist, format);
if (SUCCEEDED(StringCchVPrintfA(buf, CCHOF(buf), format, arglist)))
{
retval = strlen(buf);
}
va_end(arglist);
return retval;
}
enum XCF_Result
CFFInitFont(
UFOStruct *pUFO,
CFFFontStruct *pFont
)
{
XCF_CallbackStruct callbacks = {0};
XCF_ClientOptions options = {0};
char fontName[256];
/*
* Initialize XCF_CallbackStruct object.
*/
/* Stream output functions */
callbacks.putBytes = PutBytesAtPos;
callbacks.putBytesHook = (void PTR_PREFIX *)pUFO;
callbacks.outputPos = (XCF_OutputPosFunc)nil;
callbacks.outputPosHook = (void PTR_PREFIX *)0;
callbacks.getBytes = GetBytesFromPos;
callbacks.getBytesHook = (void PTR_PREFIX *)pUFO;
callbacks.allocate = AllocateMem;
callbacks.allocateHook = (void PTR_PREFIX *)pUFO;
callbacks.pFont = 0;
callbacks.fontLength = 0;
/* C Standard library functions */
callbacks.strlen = (XCF_strlen)StringLength;
callbacks.memcpy = (XCF_memcpy)MemCpy;
callbacks.memset = (XCF_memset)SetMemory;
callbacks.xcfSprintf = (XCF_sprintf)UFLsprintf;
callbacks.printfError = (XCF_printfError)printfError;
callbacks.atoi = (XCF_atoi)AsciiToInt;
callbacks.strtol = (XCF_strtol)StringToLong;
callbacks.atof = (XCF_atof)nil; /* not required */
callbacks.strcmp = (XCF_strcmp)StrCmp;
/* Glyph ID functions */
callbacks.gidToCharName = (XCF_GIDToCharName)GetCharName;
callbacks.gidToCID = (XCF_GIDToCID)GIDToCID;
callbacks.getCharStr = (XCF_GetCharString)nil;
callbacks.getCharStrHook = (void PTR_PREFIX *)nil;
callbacks.getFSType = (XCF_GetFSType)getFSType;
callbacks.getFSTypeHook = (void PTR_PREFIX *)pUFO;
/* GOODNAME */
callbacks.isKnownROS = (XCF_IsKnownROS)isKnownROS;
callbacks.isKnownROSHook = (void PTR_PREFIX *)pUFO;
/*
* Initialize XCF_ClientOptions object.
*/
options.fontIndex = 0; /* font index w/i a CFF font set */
options.uniqueIDMethod = pFont->info.uniqueIDMethod; /* UniqueID method */
options.uniqueID = pFont->info.uniqueID;
options.subrFlatten = (pFont->info.subrFlatten == kFlattenSubrs) ? XCF_FLATTEN_SUBRS : XCF_KEEP_SUBRS; /* Flatten subrs */
// lenIV = -1 will fail on some clones bug 354368
// options.lenIV = (pUFO->pUFL->outDev.lPSLevel > kPSLevel1) ? (unsigned int)-1 : 4;
options.lenIV = 0;
options.hexEncoding = StrmCanOutputBinary(pUFO->pUFL->hOut) ? 0 : 1;
options.eexecEncryption = (pUFO->pUFL->outDev.lPSLevel > kPSLevel1) ? 0 : 1;
options.outputCharstrType = 1; /* (pUFO->pUFL->outDev.lPSLevel > kPSLevel2) ? 2 : 1 */
options.maxBlockSize = pFont->info.maxBlockSize;
/*
* XCF_ClientOptions.dlOptions initialization
*/
if (pFont->info.usePSName)
options.dlOptions.notdefEncoding = 1;
else
options.dlOptions.notdefEncoding = 0;
options.dlOptions.useSpecialEncoding = (pFont->info.useSpecialEncoding) ? 1 : 0;
options.dlOptions.encodeName = (unsigned char PTR_PREFIX *)pUFO->pszEncodeName;
if (pFont->info.escDownloadFace)
options.dlOptions.fontName = (unsigned char PTR_PREFIX *)pUFO->pszFontName;
else
{
if (pFont->info.type1)
{
if (pUFO->subfontNumber < 0x100)
CREATE_ADCFXX_FONTNAME(UFLsprintf, fontName, CCHOF(fontName),
pUFO->subfontNumber, pFont->info.baseName);
else
CREATE_ADXXXX_FONTNAME(UFLsprintf, fontName, CCHOF(fontName),
pUFO->subfontNumber, pFont->info.baseName);
}
else
{
/* Reuse vifinfo.nPlatformID to fix #507985. */
if (pUFO->vpfinfo.nPlatformID == kUFLVPFPlatformID9x)
{
if (pUFO->lDownloadFormat == kCFFCID_H)
UFLsprintf(fontName, CCHOF(fontName), "%s%s", CFFPREFIX_H, pFont->info.baseName);
else
UFLsprintf(fontName, CCHOF(fontName), "%s%s", CFFPREFIX_V, pFont->info.baseName);
}
else
UFLsprintf(fontName, CCHOF(fontName), "%s%s", CFFPREFIX, pFont->info.baseName);
}
options.dlOptions.fontName = (unsigned char PTR_PREFIX *)fontName;
}
options.dlOptions.otherSubrNames =
(pUFO->pUFL->outDev.lPSVersion >= VER_WO_OTHERSUBRS)
? 0 : (unsigned char PTR_PREFIX * PTR_PREFIX *)pSubrNames;
return XCF_Init(&pFont->hFont, &callbacks, &options);
}
/******************************************************************************
*
* Public Functions
*
******************************************************************************/
void
CFFFontCleanUp(
UFOStruct *pUFObj
)
{
CFFFontStruct *pFont;
UFLCFFReadBuf *pReadBuf;
if (pUFObj->pAFont == nil)
return;
pFont = (CFFFontStruct *)pUFObj->pAFont->hFont;
if (pFont == nil)
return;
if (pFont->hFont)
{
XCF_CleanUp(&pFont->hFont);
pFont->hFont = nil;
}
pReadBuf = pFont->pReadBuf;
if (pReadBuf->pBuf)
{
UFLDeletePtr(pUFObj->pMem, pReadBuf->pBuf);
pReadBuf->pBuf = nil;
}
}
UFLErrCode
CFFUpdateEncodingVector1(
UFOStruct *pUFO,
const UFLGlyphsInfo *pGlyphs,
const short cGlyphs,
const UFLGlyphID *pGlyphIndices
)
{
CFFFontStruct *pFont = (CFFFontStruct *)pUFO->pAFont->hFont;
UFLHANDLE stream = pUFO->pUFL->hOut;
UFLErrCode retCode = kNoErr;
char strmbuf[256];
short i;
/* Sanity checks */
if (0 == cGlyphs)
return kNoErr;
if ((0 == pFont) || (0 == pGlyphIndices))
return kErrInvalidParam;
/*
* Do '/FontName findfont /Encoding get'.
*/
UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s findfont /Encoding get", pUFO->pszFontName);
retCode = StrmPutStringEOL(stream, strmbuf);
for (i = 0; (retCode == kNoErr) && (i < cGlyphs) && *pGlyphIndices; i++, pGlyphIndices++)
{
UFLsprintf(strmbuf, CCHOF(strmbuf), "dup %d /", i);
retCode = StrmPutString(stream, strmbuf);
if (retCode == kNoErr)
{
XCF_GlyphIDsToCharNames(pFont->hFont,
1,
(XCFGlyphID PTR_PREFIX *)pGlyphIndices, /* list of glyphIDs */
strmbuf,
sizeof(strmbuf));
retCode = StrmPutString(stream, strmbuf);
}
if (retCode == kNoErr)
retCode = StrmPutStringEOL(stream, " put");
}
StrmPutStringEOL(stream, "pop");
return retCode;
}
UFLErrCode
CFFUpdateEncodingVector(
UFOStruct *pUFO,
const short cGlyphs,
const UFLGlyphID *pGlyphIndices,
const unsigned short *pGlyphNameIndex
)
{
CFFFontStruct *pFont = (CFFFontStruct *)pUFO->pAFont->hFont;
UFLHANDLE stream = pUFO->pUFL->hOut;
UFLErrCode retCode = kNoErr;
const UFLGlyphID *pGlyphIndices2 = pGlyphIndices;
const unsigned short *pGlyphNameIndex2 = pGlyphNameIndex;
char strmbuf[256];
short i;
/* Sanity checks */
if (0 == cGlyphs)
return kNoErr;
if ((0 == pFont) || (0 == pGlyphNameIndex) || (0 == pGlyphIndices))
return kErrInvalidParam;
/*
* Do we really need to update?
*/
for (i = 0; i < cGlyphs; i++, pGlyphNameIndex2++, pGlyphIndices2++)
{
if ((*pGlyphNameIndex2 > 0) && (*pGlyphNameIndex2 <= 255))
{
if (!IS_GLYPH_SENT(pUFO->pUpdatedEncoding, *pGlyphNameIndex2))
break;
}
}
if (cGlyphs <= i)
return kNoErr;
/*
* Do '/FontName findfont /Encoding get'.
*/
UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s findfont /Encoding get", pUFO->pszFontName);
retCode = StrmPutStringEOL(stream, strmbuf);
for (i = 0; (retCode == kNoErr) && (i < cGlyphs); i++, pGlyphNameIndex++, pGlyphIndices++)
{
if ((*pGlyphNameIndex > 0) && (*pGlyphNameIndex <= 255))
{
if (!IS_GLYPH_SENT(pUFO->pUpdatedEncoding, *pGlyphNameIndex))
{
/*
* Do "dup index /Charactername put."
*/
UFLsprintf(strmbuf, CCHOF(strmbuf), "dup %d /", *pGlyphNameIndex);
retCode = StrmPutString(stream, strmbuf);
if (kNoErr == retCode)
{
if (XCF_Ok == XCF_GlyphIDsToCharNames(pFont->hFont,
1,
(XCFGlyphID PTR_PREFIX *)pGlyphIndices, /* list of glyphIDs */
strmbuf,
sizeof(strmbuf)))
{
retCode = StrmPutString(stream, strmbuf);
}
else
retCode = kErrUnknown;
}
if (kNoErr == retCode)
retCode = StrmPutStringEOL(stream, " put");
if (kNoErr == retCode)
SET_GLYPH_SENT_STATUS(pUFO->pUpdatedEncoding, *pGlyphNameIndex);
}
}
}
StrmPutStringEOL(stream, "pop");
return retCode;
}
UFLErrCode
CFFCreateBaseFont(
UFOStruct *pUFObj,
const UFLGlyphsInfo *pGlyphs,
unsigned long *pVMUsage,
char *pHostFontName
)
{
CFFFontStruct *pFont = (CFFFontStruct *)pUFObj->pAFont->hFont;
UFLHANDLE stream = pUFObj->pUFL->hOut;
UFLErrCode retCode = kNoErr;
char strmbuf[512];
/* Sanity checks */
if (pUFObj->flState < kFontInit)
return kErrInvalidState;
if ((pFont == nil) || (pFont->hFont == nil))
return kErrInvalidHandle;
/*
* Download procsets.
*/
switch (pUFObj->lDownloadFormat)
{
case kCFF:
if (pUFObj->pUFL->outDev.lPSVersion <= VER_WO_OTHERSUBRS)
{
/*
* Only download the required OtherSubr procset if the printer
* version is less than 51 and we have not download anything.
*/
if (pUFObj->pUFL->outDev.pstream->pfDownloadProcset == 0)
return kErrDownloadProcset;
if (!pUFObj->pUFL->outDev.pstream->pfDownloadProcset(pUFObj->pUFL->outDev.pstream, kCFFHeader))
return kErrDownloadProcset;
}
break;
case kCFFCID_H:
case kCFFCID_V:
if (!pUFObj->pUFL->outDev.pstream->pfDownloadProcset(pUFObj->pUFL->outDev.pstream, kCMap_FF))
return kErrDownloadProcset;
if (pUFObj->bPatchQXPCFFCID)
{
if (!pUFObj->pUFL->outDev.pstream->pfDownloadProcset(pUFObj->pUFL->outDev.pstream, kCMap_90msp))
return kErrDownloadProcset;
}
}
/*
* Donwload the font's dictionary and the glyph data.
*/
if (!UFO_FONT_INIT2(pUFObj))
{
enum XCF_Result status;
/*
* Fixed bug 366539. hasvmtx is used to determine whether to call the
* CFFUpdateMetrics2 function later.
*/
unsigned long tblSize = GETTTFONTDATA(pUFObj,
VMTX_TABLE, 0L,
nil, 0L,
pFont->info.fData.fontIndex);
pUFObj->pAFont->hasvmtx = tblSize ? 1 : 0;
if (!HOSTFONT_IS_VALID_UFO(pUFObj))
{
status = XCF_DownloadFontIncr(pFont->hFont,
pGlyphs->sCount,
pGlyphs->pGlyphIndices,
(pGlyphs->pCharIndex == 0)
? nil
: (unsigned char PTR_PREFIX * PTR_PREFIX *)pGlyphs->ppGlyphNames,
pVMUsage);
if (XCF_Ok != status)
retCode = kErrXCFCall;
}
}
/*
* %hostfont% support
* When this is a %hostfont% emit %%IncludeResource DSC comment prior to
* create the font.
*/
if ((kNoErr == retCode) && HOSTFONT_IS_VALID_UFO(pUFObj) && !UFO_FONT_INIT2(pUFObj))
{
UFLsprintf(strmbuf, CCHOF(strmbuf), "\n%%%%IncludeResource: %s %s",
(pUFObj->lDownloadFormat == kCFF) ? "font" : "CIDFont",
pHostFontName);
if (kNoErr == retCode)
retCode = StrmPutStringEOL(stream, strmbuf);
}
if ((kNoErr == retCode) && IS_CFFCID(pUFObj->lDownloadFormat))
{
/*
* Instanciate Identity-H or -V CMap.
*
* When 'vrt2' feature is enabled (and which is default for OTF based
* CJKV fonts), simply compose Identity-V CMap and the CIDFont
* downloaded suffice.
*/
if (pUFObj->lDownloadFormat == kCFFCID_H)
{
retCode = StrmPutStringEOL(stream, "CMAP-WinCharSetFFFF-H");
/* Special for Quark */
if ((kNoErr == retCode) && pUFObj->bPatchQXPCFFCID)
retCode = StrmPutStringEOL(stream, "CMAP-90msp-RKSJ-H");
}
else
{
retCode = StrmPutStringEOL(stream, "CMAP-WinCharSetFFFF-V");
/* Special for Quark */
if ((kNoErr == retCode) && pUFObj->bPatchQXPCFFCID)
retCode = StrmPutStringEOL(stream, "CMAP-90msp-RKSJ-H CMAP-90msp-RKSJ-QV");
}
if (kNoErr == retCode)
{
/*
* Create the CID-Keyed font.
*/
UFLBool bRequire_vmtx = pUFObj->pAFont->hasvmtx && HOSTFONT_REQUIRE_VMTX;
if (pUFObj->lDownloadFormat == kCFFCID_H)
UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s /WinCharSetFFFF-H", pUFObj->pszFontName);
else
UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s /WinCharSetFFFF-V", pUFObj->pszFontName);
if (kNoErr == retCode)
retCode = StrmPutStringEOL(stream, strmbuf);
if (!HOSTFONT_IS_VALID_UFO(pUFObj))
{
/* Reuse vifinfo.nPlatformID to fix #507985. */
if (pUFObj->vpfinfo.nPlatformID == kUFLVPFPlatformID9x)
{
if (pUFObj->lDownloadFormat == kCFFCID_H)
UFLsprintf(strmbuf, CCHOF(strmbuf), "[/%s%s] composefont pop", CFFPREFIX_H, pFont->info.baseName);
else
UFLsprintf(strmbuf, CCHOF(strmbuf), "[/%s%s] composefont pop", CFFPREFIX_V, pFont->info.baseName);
}
else
UFLsprintf(strmbuf, CCHOF(strmbuf), "[/%s%s] composefont pop", CFFPREFIX, pFont->info.baseName);
}
else if (!bRequire_vmtx)
UFLsprintf(strmbuf, CCHOF(strmbuf), "[/%s] composefont pop", pHostFontName);
else
{
if (UFL_CIDFONT_SHARED)
{
if (!UFO_FONT_INIT2(pUFObj))
UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s%s %s /%s hfMkCIDFont",
pHostFontName, HFPOSTFIX, HFCIDCDEVPROC, pHostFontName);
else
UFLsprintf(strmbuf, CCHOF(strmbuf), "[/%s%s] composefont pop", pHostFontName, HFPOSTFIX);
}
else
{
UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s%s%s %s /%s hfMkCIDFont",
pHostFontName, HFPOSTFIX,
(pUFObj->lDownloadFormat == kCFFCID_H) ? "h" : "v",
HFCIDCDEVPROC, pHostFontName);
}
}
if (kNoErr == retCode)
retCode = StrmPutStringEOL(stream, strmbuf);
/*
* Special for Quark
*/
if ((kNoErr == retCode) && pUFObj->bPatchQXPCFFCID)
{
UFLsprintf(strmbuf, CCHOF(strmbuf), "/%sQ", pUFObj->pszFontName);
retCode = StrmPutString(stream, strmbuf);
if (pUFObj->lDownloadFormat == kCFFCID_H)
{
if (!HOSTFONT_IS_VALID_UFO(pUFObj))
{
/* Reuse vifinfo.nPlatformID to fix #507985. */
if (pUFObj->vpfinfo.nPlatformID == kUFLVPFPlatformID9x)
UFLsprintf(strmbuf, CCHOF(strmbuf), " /90msp-RKSJ-H [/%s%s] composefont pop",
CFFPREFIX_H, pFont->info.baseName);
else
UFLsprintf(strmbuf, CCHOF(strmbuf), " /90msp-RKSJ-H [/%s%s] composefont pop",
CFFPREFIX, pFont->info.baseName);
}
else if (!bRequire_vmtx)
{
UFLsprintf(strmbuf, CCHOF(strmbuf), " /90msp-RKSJ-H [/%s] composefont pop",
pHostFontName);
}
else
{
if (UFL_CIDFONT_SHARED)
UFLsprintf(strmbuf, CCHOF(strmbuf), " /90msp-RKSJ-H [/%s%s] composefont pop",
pHostFontName, HFPOSTFIX);
else
UFLsprintf(strmbuf, CCHOF(strmbuf), " /90msp-RKSJ-H [/%s%s%s] composefont pop",
pHostFontName, HFPOSTFIX, "h");
}
}
else
{
/* Added 'dup dup' for bug 346287. */
if (!HOSTFONT_IS_VALID_UFO(pUFObj))
{
/* Reuse vifinfo.nPlatformID to fix #507985. */
if (pUFObj->vpfinfo.nPlatformID == kUFLVPFPlatformID9x)
UFLsprintf(strmbuf, CCHOF(strmbuf), " /90msp-RKSJ-QV [/%s%s dup dup] composefont pop",
CFFPREFIX_V, pFont->info.baseName);
else
UFLsprintf(strmbuf, CCHOF(strmbuf), " /90msp-RKSJ-QV [/%s%s dup dup] composefont pop",
CFFPREFIX, pFont->info.baseName);
}
else if (!bRequire_vmtx)
{
UFLsprintf(strmbuf, CCHOF(strmbuf), " /90msp-RKSJ-QV [/%s dup dup] composefont pop",
pHostFontName);
}
else
{
if (UFL_CIDFONT_SHARED)
UFLsprintf(strmbuf, CCHOF(strmbuf), " /90msp-RKSJ-QV [/%s%s dup dup] composefont pop",
pHostFontName, HFPOSTFIX);
else
UFLsprintf(strmbuf, CCHOF(strmbuf), " /90msp-RKSJ-QV [/%s%s%s dup dup] composefont pop",
pHostFontName, HFPOSTFIX, "v");
}
}
if (kNoErr == retCode)
retCode = StrmPutStringEOL(stream, strmbuf);
}
}
}
else if ((kNoErr == retCode) && HOSTFONT_IS_VALID_UFO(pUFObj))
{
/*
* Redefine the font using the already existing OpenType host font with
* a unique name so that we can reencode its encoding vector freely. We
* don't want empty CharStrings so that we give false to hfRedefFont.
*/
UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s false /%s hfRedefFont",
pUFObj->pszFontName, pHostFontName);
if (kNoErr == retCode)
retCode = StrmPutStringEOL(stream, strmbuf);
}
/*
* Change the font state. (skip kFontHeaderDownloaded state.)
*/
if (kNoErr == retCode)
pUFObj->flState = kFontHasChars;
return retCode;
}
UFLErrCode
CFFAddChars(
UFOStruct *pUFObj,
const UFLGlyphsInfo *pGlyphs,
unsigned long *pVMUsage
)
{
CFFFontStruct *pFont = (CFFFontStruct *)pUFObj->pAFont->hFont;
UFLErrCode retCode = kNoErr;
/* Sanity checks */
if (pUFObj->flState < kFontHeaderDownloaded)
return kErrInvalidState;
if ((pFont == nil) || (pFont->hFont == nil))
return kErrInvalidHandle;
/*
* Download the glyphs.
*/
if (!HOSTFONT_IS_VALID_UFO(pUFObj))
{
enum XCF_Result status;
status = XCF_DownloadFontIncr(pFont->hFont,
pGlyphs->sCount,
pGlyphs->pGlyphIndices,
(pGlyphs->pCharIndex == 0)
? nil
: (unsigned char PTR_PREFIX * PTR_PREFIX *)pGlyphs->ppGlyphNames,
pVMUsage);
if (XCF_Ok != status)
retCode = kErrXCFCall;
}
/*
* Change the font state.
*/
if (kNoErr == retCode)
pUFObj->flState = kFontHasChars;
return retCode;
}
UFLErrCode
CFFUpdateMetrics2(
UFOStruct *pUFObj,
const UFLGlyphsInfo *pGlyphs,
char *pHostFontName
)
{
UFLErrCode retVal = kNoErr;
CFFFontStruct *pFont = (CFFFontStruct *)pUFObj->pAFont->hFont;
UFLHANDLE stream = pUFObj->pUFL->hOut;
char strmbuf[256];
unsigned short wIndex;
UFLBool bRequire_vmtx = pUFObj->pAFont->hasvmtx && HOSTFONT_REQUIRE_VMTX;
if ((!HOSTFONT_IS_VALID_UFO(pUFObj) || bRequire_vmtx) && (pGlyphs->sCount > 0))
{
UFLGlyphID *glyphs = pGlyphs->pGlyphIndices;
unsigned short i;
unsigned short *pCIDs = (unsigned short*)UFLNewPtr(pUFObj->pMem, pGlyphs->sCount * sizeof (unsigned short));
if (pCIDs)
retVal = CFFGIDsToCIDs(pFont, pGlyphs->sCount, glyphs, pCIDs);
else
retVal = kErrOutOfMemory;
if (kNoErr != retVal)
{
if (pCIDs)
UFLDeletePtr(pUFObj->pMem, pCIDs);
return retVal;
}
/*
* Check pUFObj->pAFont->pCodeGlyphs to see if we really need to update
* it.
*/
for (i = 0; i < (unsigned short) pGlyphs->sCount; i++)
{
unsigned short wIndex = (unsigned short)(glyphs[i] & 0x0000FFFF); /* LOWord is the real GID. */
if (wIndex >= UFO_NUM_GLYPHS(pUFObj))
continue;
if (!IS_GLYPH_SENT(pUFObj->pAFont->pDownloadedGlyphs, wIndex))
{
long em, w1y, vx, vy, tsb, vasc;
UFLBool bUseDef;
GetMetrics2FromTTF(pUFObj, wIndex, &em, &w1y, &vx, &vy, &tsb, &bUseDef, 0, &vasc);
UFLsprintf(strmbuf, CCHOF(strmbuf), "%ld [0 %ld %ld %ld] ", (long)pCIDs[i], -w1y, vx, tsb);
retVal = StrmPutString(stream, strmbuf);
if (!HOSTFONT_IS_VALID_UFO(pUFObj))
{
/* Reuse vifinfo.nPlatformID to fix #507985. */
if (pUFObj->vpfinfo.nPlatformID == kUFLVPFPlatformID9x)
{
if (pUFObj->lDownloadFormat == kCFFCID_H)
UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s%s T0AddCFFMtx2", CFFPREFIX_H, pFont->info.baseName);
else
UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s%s T0AddCFFMtx2", CFFPREFIX_V, pFont->info.baseName);
}
else
UFLsprintf(strmbuf, CCHOF(strmbuf), " /%s%s T0AddCFFMtx2", CFFPREFIX, pFont->info.baseName);
}
else
{
if (UFL_CIDFONT_SHARED)
UFLsprintf(strmbuf, CCHOF(strmbuf), " /%s%s T0AddCFFMtx2", pHostFontName, HFPOSTFIX);
else
UFLsprintf(strmbuf, CCHOF(strmbuf), " /%s%s%s T0AddCFFMtx2",
pHostFontName, HFPOSTFIX,
(pUFObj->lDownloadFormat == kCFFCID_H) ? "h" : "v");
}
if (kNoErr == retVal)
retVal = StrmPutStringEOL(stream, strmbuf);
if (kNoErr == retVal)
SET_GLYPH_SENT_STATUS(pUFObj->pAFont->pDownloadedGlyphs, wIndex);
}
}
UFLDeletePtr(pUFObj->pMem, pCIDs);
}
return retVal;
}
UFLErrCode
CFFReencode(
UFOStruct *pUFObj,
const UFLGlyphsInfo *pGlyphs,
unsigned long *pVMUsage,
char *pHostFontName
)
{
CFFFontStruct *pFont = (CFFFontStruct *)pUFObj->pAFont->hFont;
UFLErrCode retCode = kNoErr;
/* Sanity checks */
if (pUFObj->flState < kFontHeaderDownloaded)
return kErrInvalidState;
if ((pFont == nil) || (pFont->hFont == nil))
return kErrInvalidHandle;
/*
* Reencode the encoding vector and define good glyph names.
*/
if (kNoErr == retCode)
{
if (pFont->info.usePSName)
{
if (pGlyphs->pCharIndex == 0)
retCode = CFFUpdateEncodingVector1(
(UFOStruct *)pUFObj,
pGlyphs,
pGlyphs->sCount,
pGlyphs->pGlyphIndices);
else
retCode = CFFUpdateEncodingVector(
(UFOStruct *)pUFObj,
pGlyphs->sCount,
pGlyphs->pGlyphIndices,
pGlyphs->pCharIndex);
}
/*
* Adobe Bug #366539 and #388111: Download Metrics2 for vertical writing
*
* Note: to remember the glyphs downloaded for Metrics2 we use
* pUFObj->pAFont->pDownloadedGlyphs. There is another bitmap data,
* pUFObj->pAFont->pCodeGlyphs, to remember the glyphs downloaded
* for GoodGlyphName. They must be used independently. Do not use
* pDownloadedGlyphs for GoodGlyphName and pCodeGlyphs for Metrics2.
*/
if ((kNoErr == retCode) && IS_CFFCID(pUFObj->lDownloadFormat))
{
retCode = CFFUpdateMetrics2(pUFObj, pGlyphs, pHostFontName);
}
/*
* GOODNAME
*/
if ((kNoErr == retCode)
&& (pGlyphs->sCount > 0)
&& (pUFObj->dwFlags & UFO_HasG2UDict)
&& (IS_CFFCID(pUFObj->lDownloadFormat))
&& !(pUFObj->pAFont->knownROS))
{
UFLGlyphID *glyphs = pGlyphs->pGlyphIndices;
unsigned short i;
/*
* Check pUFObj->pAFont->pCodeGlyphs to see if we really need to
* update it.
*/
for (i = 0; i < (unsigned short) pGlyphs->sCount; i++)
{
unsigned short wIndex = (unsigned short)(glyphs[i] & 0x0000FFFF); /* LOWord is the real GID. */
if (wIndex >= UFO_NUM_GLYPHS(pUFObj))
continue;
if (!IS_GLYPH_SENT(pUFObj->pAFont->pCodeGlyphs, wIndex))
{
/*
* Found at least one not updated. Do it (once) for all.
*/
retCode = UpdateCodeInfo(pUFObj, pGlyphs, 0);
break;
}
}
}
}
return retCode;
}
UFLErrCode
CFFFontDownloadIncr(
UFOStruct *pUFObj,
const UFLGlyphsInfo *pGlyphs,
unsigned long *pVMUsage,
unsigned long *pFCUsage
)
{
CFFFontStruct *pFont = (CFFFontStruct *)pUFObj->pAFont->hFont;
UFLErrCode retCode = kNoErr;
char *pHostFontName = nil;
if (pFCUsage)
*pFCUsage = 0;
/*
* Sanity checks.
*/
if ((pGlyphs == nil) || (pGlyphs->pGlyphIndices == nil) || (pGlyphs->sCount == 0))
return kErrInvalidParam;
/*
* No need to download if the full font has already been downloaded.
*/
if (pUFObj->flState == kFontFullDownloaded)
return kNoErr;
/*
* Check %hostfont% status prior to download anything.
*/
HostFontValidateUFO(pUFObj, &pHostFontName);
if (pUFObj->flState == kFontInit)
{
/*
* Create a base font (and the glyphs) if it has not been done yet.
*/
retCode = CFFCreateBaseFont(pUFObj, pGlyphs, pVMUsage, pHostFontName);
if (kNoErr == retCode)
retCode = CFFReencode(pUFObj, pGlyphs, pVMUsage, pHostFontName);
}
else
{
/*
* Download the glyphs.
*/
retCode = CFFAddChars(pUFObj, pGlyphs, pVMUsage);
if (kNoErr == retCode)
retCode = CFFReencode(pUFObj, pGlyphs, pVMUsage, pHostFontName);
}
return retCode;
}
UFLErrCode
CFFVMNeeded(
const UFOStruct *pUFO,
const UFLGlyphsInfo *pGlyphs,
unsigned long *pVMNeeded,
unsigned long *pFCNeeded
)
{
CFFFontStruct *pFont = (CFFFontStruct *)pUFO->pAFont->hFont;
enum XCF_Result status;
unsigned short cDLGlyphs;
if (pVMNeeded)
*pVMNeeded = 0;
if (pFCNeeded)
*pFCNeeded = 0;
if ((pFont == nil) || (pFont->hFont == nil))
return kErrInvalidHandle;
status = XCF_CountDownloadGlyphs(pFont->hFont,
pGlyphs->sCount,
(XCFGlyphID *)pGlyphs->pGlyphIndices,
&cDLGlyphs);
if (XCF_Ok != status)
return kErrUnknown;
if (!HOSTFONT_IS_VALID_UFO(pUFO))
{
if (pVMNeeded)
*pVMNeeded = cDLGlyphs * kVMTTT1Char;
if (pUFO->flState == kFontInit)
{
if (pVMNeeded)
*pVMNeeded += kVMTTT1Header;
}
}
else
{
unsigned long tblSize = GETTTFONTDATA(pUFO,
VMTX_TABLE, 0L,
nil, 0L,
pFont->info.fData.fontIndex);
if (tblSize && HOSTFONT_REQUIRE_VMTX)
{
if (pVMNeeded)
*pVMNeeded = cDLGlyphs * HFVMM2SZ;
}
}
return kNoErr;
}
UFLErrCode
CFFUndefineFont(
UFOStruct *pUFO
)
{
CFFFontStruct *pFont = (CFFFontStruct *)pUFO->pAFont->hFont;
UFLHANDLE stream = pUFO->pUFL->hOut;
UFLErrCode retVal = kNoErr;
char strmbuf[256];
if ((pFont == nil) || (pFont->hFont == nil))
return kErrInvalidHandle;
if (pUFO->flState == kFontInit)
return retVal;
if ((pUFO->lDownloadFormat == kCFFCID_H) || (pUFO->lDownloadFormat == kCFFCID_V))
{
/* Reuse vifinfo.nPlatformID to fix #507985. */
if (pUFO->vpfinfo.nPlatformID == kUFLVPFPlatformID9x)
{
if (pUFO->lDownloadFormat == kCFFCID_H)
UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s%s /CIDFont UDR", CFFPREFIX_H, pFont->info.baseName);
else
UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s%s /CIDFont UDR", CFFPREFIX_V, pFont->info.baseName);
}
else
UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s%s /CIDFont UDR", CFFPREFIX, pFont->info.baseName);
retVal = StrmPutStringEOL(stream, strmbuf);
}
UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s UDF", pUFO->pszFontName);
if (kNoErr == retVal)
retVal = StrmPutStringEOL(stream, strmbuf);
return retVal;
}
UFLErrCode
CFFGIDsToCIDs(
const CFFFontStruct *pFont,
const short cGlyphs,
const UFLGlyphID *pGIDs,
unsigned short *pCIDs
)
{
unsigned short int *pCurCIDs = (unsigned short int *)pCIDs;
UFLGlyphID *pCurGIDs = (UFLGlyphID *)pGIDs;
UFLErrCode retCode = kNoErr;
enum XCF_Result status;
short i;
for (i = 0; i < cGlyphs; i++)
{
status = XCF_GlyphIDsToCIDs(pFont->hFont,
1,
(XCFGlyphID PTR_PREFIX *)pCurGIDs++, /* list of glyphIDs */
pCurCIDs++);
if (XCF_Ok != status)
{
retCode = kErrUnknown;
break;
}
}
return retCode;
}
UFOStruct *
CFFFontInit(
const UFLMemObj *pMem,
const UFLStruct *pUFL,
const UFLRequest *pRequest,
UFLBool *pTestRestricted
)
{
enum XCF_Result status = XCF_InternalError;
CFFFontStruct *pFont = nil;
UFOStruct *pUFObj = (UFOStruct*)UFLNewPtr(pMem, sizeof (UFOStruct));
UFLCFFFontInfo *pInfo;
if (pUFObj == 0)
return nil;
/* Initialize data. */
UFOInitData(pUFObj, UFO_CFF, pMem, pUFL, pRequest,
(pfnUFODownloadIncr) CFFFontDownloadIncr,
(pfnUFOVMNeeded) CFFVMNeeded,
(pfnUFOUndefineFont) CFFUndefineFont,
(pfnUFOCleanUp) CFFFontCleanUp,
(pfnUFOCopy) CopyFont);
/*
* pszFontName should be ready/allocated. If not, cannot continue.
*/
if ((pUFObj->pszFontName == nil) || (pUFObj->pszFontName[0] == '\0'))
{
UFLDeletePtr(pMem, pUFObj);
return nil;
}
pInfo = (UFLCFFFontInfo *)pRequest->hFontInfo;
if (NewFont(pUFObj, sizeof(CFFFontStruct), pInfo->fData.maxGlyphs) == kNoErr)
{
pFont = (CFFFontStruct *)pUFObj->pAFont->hFont;
pFont->info = *pInfo;
pFont->pReadBuf = &pFont->info.readBuf;
/* a convenient pointer */
pUFObj->pFData = &(pFont->info.fData);
pFont->info.fData.cNumGlyphs = GetNumGlyphs(pUFObj);
if (pUFObj->pUpdatedEncoding == 0)
pUFObj->pUpdatedEncoding = (unsigned char *)UFLNewPtr(pMem, GLYPH_SENT_BUFSIZE(256));
pFont->hFont = 0;
status = CFFInitFont(pUFObj, pFont);
}
if ((XCF_Ok != status) || (pFont == nil) || (pFont->hFont == 0))
{
vDeleteFont(pUFObj);
UFLDeletePtr(pUFObj->pMem, pUFObj);
return nil;
}
else
{
if (pTestRestricted)
{
unsigned char uc;
unsigned short int us;
XCF_SubsetRestrictions(pFont->hFont, &uc, &us);
*pTestRestricted = (BOOL)uc;
}
else
status = XCF_ProcessCFF(pFont->hFont);
if (XCF_Ok == status)
pUFObj->flState = kFontInit;
else
{
vDeleteFont(pUFObj);
UFLDeletePtr(pUFObj->pMem, pUFObj);
return nil;
}
}
return pUFObj;
}