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.
2812 lines
98 KiB
2812 lines
98 KiB
/* @(#)CM_VerSion xcf_t1.c atm09 1.3 16499.eco sum= 63806 atm09.002 */
|
|
/* @(#)CM_VerSion xcf_t1.c atm08 1.6 16343.eco sum= 18288 atm08.005 */
|
|
/***********************************************************************/
|
|
/* */
|
|
/* Copyright 1995-1996 Adobe Systems Incorporated. */
|
|
/* All rights reserved. */
|
|
/* */
|
|
/* Patents Pending */
|
|
/* */
|
|
/* NOTICE: All information contained herein is the property of Adobe */
|
|
/* Systems Incorporated. Many of the intellectual and technical */
|
|
/* concepts contained herein are proprietary to Adobe, are protected */
|
|
/* as trade secrets, and are made available only to Adobe licensees */
|
|
/* for their internal use. Any reproduction or dissemination of this */
|
|
/* software is strictly forbidden unless prior written permission is */
|
|
/* obtained from Adobe. */
|
|
/* */
|
|
/* PostScript and Display PostScript are trademarks of Adobe Systems */
|
|
/* Incorporated or its subsidiaries and may be registered in certain */
|
|
/* jurisdictions. */
|
|
/* */
|
|
/***********************************************************************/
|
|
|
|
/***********************************************************************
|
|
Original version: John Felton, April 17, 1996
|
|
************************************************************************/
|
|
|
|
/* -------------------------------------------------------------------------
|
|
Header Includes
|
|
--------------------------------------------------------------------------- */
|
|
|
|
#include "xcf_pub.h"
|
|
#include "xcf_priv.h"
|
|
#include <math.h>
|
|
#ifdef T13
|
|
#include "xcf_t13.h"
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
static Card8 HexTable[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
|
|
|
#define MAX_LINE_LENGTH 1024
|
|
#define REAL_TO_INT(x) (long)(x < 0 ? x - 0.5 : x + 0.5)
|
|
|
|
/* Definitions of font data replacement points. */
|
|
#define XCF_FONTNAME 0
|
|
#define XCF_ENCODING 1
|
|
#define XCF_UID 2
|
|
#define XCF_XUID 3
|
|
|
|
/* The following items are artifacts of the Type 1 format and are */
|
|
/* no longer considered necessary for the proper functioning of fonts. */
|
|
#if 1
|
|
#define T1_READONLY ""
|
|
#define T1_NOACCESS ""
|
|
#else /* old way */
|
|
#define T1_READONLY " readonly "
|
|
#define T1_NOACCESS " noaccess "
|
|
#endif /*1*/
|
|
|
|
static void BufferEncrypt(XCF_Handle h,
|
|
Card8 PTR_PREFIX *inBuf,
|
|
Card8 PTR_PREFIX *outBuf,
|
|
Int32 inLen,
|
|
Card32 PTR_PREFIX *outLen,
|
|
Card16 PTR_PREFIX *KeyP,
|
|
boolean hexEncode)
|
|
{
|
|
register Card8 Cipher;
|
|
register Card8 PTR_PREFIX *PlainSource = inBuf;
|
|
register Card8 PTR_PREFIX *CipherDest = outBuf;
|
|
register Card16 R = *KeyP;
|
|
Card8 totalEOLs = 0;
|
|
|
|
if (!hexEncode) /* Binary encode */
|
|
{ *outLen = inLen;
|
|
|
|
while (--inLen >= 0)
|
|
{ Cipher = (*PlainSource++ ^ (Card8)(R >> 8));
|
|
R = (Card16)(((Card16)Cipher + R) * 52845 + 22719);
|
|
*CipherDest++ = Cipher;
|
|
} /* end while */
|
|
} /* end if */
|
|
else /* Hex Encode */
|
|
{ Card8 t;
|
|
*outLen = (inLen << 1);
|
|
|
|
while (--inLen >= 0)
|
|
{ Cipher = (*PlainSource++ ^ (Card8)(R >> 8));
|
|
R = (Card16)(((Card16)Cipher + R) * 52845 + 22719);
|
|
t = (Card8)(((Cipher >> 4) & 0x0F) + 0x30);
|
|
if (t > 0x39)
|
|
t += 7;
|
|
*CipherDest++ = t;
|
|
t = (Card8)((Cipher & 0x0F) + 0x30);
|
|
if (t > 0x39)
|
|
t += 7;
|
|
*CipherDest++ = t;
|
|
h->outBuffer.charsOnLine+=2;
|
|
if (h->outBuffer.charsOnLine > EOL_SPACING)
|
|
{
|
|
#if 0
|
|
*CipherDest++ = '\r';
|
|
*CipherDest++ = '\n';
|
|
totalEOLs += 2;
|
|
#else
|
|
Card8 PTR_PREFIX *p;
|
|
for (p = (Card8 *)XCF_NEW_LINE; *p; ++p)
|
|
{
|
|
*CipherDest++ = *p;
|
|
totalEOLs += 1;
|
|
}
|
|
#endif
|
|
h->outBuffer.charsOnLine = 0;
|
|
} /* end if */
|
|
} /* end while */
|
|
|
|
*outLen += totalEOLs;
|
|
} /* end else */
|
|
|
|
*KeyP = R;
|
|
} /* end BufferEncrypt() */
|
|
|
|
static void BufferHexEncode(XCF_Handle h,
|
|
Card8 PTR_PREFIX *inBuf,
|
|
Card8 PTR_PREFIX *outBuf,
|
|
Int32 inLen,
|
|
Card32 PTR_PREFIX *outLen
|
|
)
|
|
{
|
|
Card8 Datum;
|
|
Int32 i;
|
|
|
|
*outLen = (inLen << 1);
|
|
h->outBuffer.charsOnLine = 0;
|
|
for (i = 0; i < inLen; i++) /* for all input data */
|
|
{
|
|
Datum = *inBuf++;
|
|
*outBuf++ = HexTable[((Card8)(Datum >> 4)) & 0x0f];
|
|
*outBuf++ = HexTable[((Card8)Datum) & 0x0f];
|
|
h->outBuffer.charsOnLine+=2;
|
|
|
|
if (h->outBuffer.charsOnLine > EOL_SPACING) /* End of the line reached */
|
|
{
|
|
#if 0
|
|
*outBuf++ = '\r';
|
|
*outBuf++ = '\n';
|
|
*outLen += 2;
|
|
#else
|
|
Card8 PTR_PREFIX *p;
|
|
for (p = (Card8 *)XCF_NEW_LINE; *p; ++p)
|
|
{
|
|
*outBuf++ = *p;
|
|
*outLen += 1;
|
|
}
|
|
#endif
|
|
h->outBuffer.charsOnLine = 0;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
static void WriteSizedNumber(XCF_Handle h, Card8 PTR_PREFIX *data, Card32
|
|
length)
|
|
{
|
|
Card32 bytesWritten;
|
|
|
|
if (h->options.hexEncoding)
|
|
{
|
|
BufferHexEncode(h, data, h->outBuffer.eexecEncodeBuffer, length,
|
|
&bytesWritten);
|
|
XCF_PutData(h, h->outBuffer.eexecEncodeBuffer, bytesWritten);
|
|
}
|
|
else
|
|
XCF_PutData(h, data, length);
|
|
}
|
|
|
|
#if HAS_COOLTYPE_UFL == 0
|
|
static
|
|
#endif
|
|
void PutSizedNumber(XCF_Handle h, Card32 value, Card16 size)
|
|
{
|
|
Card8 data;
|
|
|
|
switch (size)
|
|
{
|
|
case 4:
|
|
data = (Card8) (value >> 24 & 0xff);
|
|
WriteSizedNumber(h, &data, 1);
|
|
case 3:
|
|
data = (Card8) (value >> 16 & 0xff);
|
|
WriteSizedNumber(h, &data, 1);
|
|
case 2:
|
|
data = (Card8) (value >> 8 & 0xff);
|
|
WriteSizedNumber(h, &data, 1);
|
|
case 1:
|
|
data = (Card8) (value & 0xff);
|
|
WriteSizedNumber(h, &data, 1);
|
|
break;
|
|
default:
|
|
XCF_FATAL_ERROR(h, XCF_IndexOutOfRange, "bad size on PutSizedNumber", size);
|
|
}
|
|
}
|
|
|
|
static void HexEncodeCharString(XCF_Handle h, Card8 PTR_PREFIX *pData,
|
|
Card32 length)
|
|
{
|
|
Card32 blockSize, encodedBlockSize;
|
|
|
|
while (length > 0)
|
|
{
|
|
blockSize = MIN(length, MAX_ENCODE_LENGTH);
|
|
BufferHexEncode(h, pData, h->outBuffer.eexecEncodeBuffer, blockSize,
|
|
&encodedBlockSize);
|
|
XCF_PutData(h, h->outBuffer.eexecEncodeBuffer, encodedBlockSize);
|
|
length -= blockSize;
|
|
pData += blockSize;
|
|
}
|
|
}
|
|
|
|
void XT1_PutT1Data(XCF_Handle h, Card8 PTR_PREFIX *pData, Card32 length)
|
|
{
|
|
Card32 blockSize, encodedBlockSize;
|
|
|
|
if (!h->outBuffer.eexecOn)
|
|
XCF_PutData(h, pData, length);
|
|
else
|
|
{
|
|
while (length > 0)
|
|
{
|
|
blockSize = MIN(length,MAX_ENCODE_LENGTH);
|
|
BufferEncrypt(h, pData, h->outBuffer.eexecEncodeBuffer,
|
|
blockSize, &encodedBlockSize, &h->outBuffer.eexecKey,
|
|
h->options.hexEncoding);
|
|
XCF_PutData(h, h->outBuffer.eexecEncodeBuffer, encodedBlockSize);
|
|
length -= blockSize;
|
|
pData += blockSize;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if HAS_COOLTYPE_UFL==0
|
|
static
|
|
#endif
|
|
Card32 PutType1CharString(XCF_Handle h, Card8 PTR_PREFIX *pData, Card32 length) {
|
|
Card32 blockSize, encodedBlockSize;
|
|
Card16 lenIVKey;
|
|
Card32 bytesWritten = length;
|
|
|
|
if (h->options.lenIV == -1)
|
|
{
|
|
if (h->options.hexEncoding)
|
|
HexEncodeCharString(h, pData, length);
|
|
else
|
|
XT1_PutT1Data(h, pData, length);
|
|
}
|
|
else
|
|
#ifdef T13
|
|
if (!XT13_PutCharString(h, pData, length, &bytesWritten))
|
|
#endif
|
|
{
|
|
bytesWritten += h->options.lenIV;
|
|
lenIVKey = LEN_IV_INITIAL_KEY;
|
|
BufferEncrypt(h, h->outBuffer.lenIVInitialBytes,
|
|
h->outBuffer.charStringEncodeBuffer, h->options.lenIV,
|
|
&encodedBlockSize, &lenIVKey, false);
|
|
if (h->options.hexEncoding && !h->outBuffer.eexecOn)
|
|
HexEncodeCharString(h, h->outBuffer.charStringEncodeBuffer, encodedBlockSize);
|
|
else
|
|
XT1_PutT1Data(h, h->outBuffer.charStringEncodeBuffer, encodedBlockSize);
|
|
while (length > 0)
|
|
{
|
|
blockSize = MIN(length,MAX_ENCODE_LENGTH);
|
|
BufferEncrypt(h, pData, h->outBuffer.charStringEncodeBuffer, blockSize, &encodedBlockSize, &lenIVKey, false);
|
|
if (h->options.hexEncoding && !h->outBuffer.eexecOn)
|
|
HexEncodeCharString(h, h->outBuffer.charStringEncodeBuffer, encodedBlockSize);
|
|
else
|
|
XT1_PutT1Data(h, h->outBuffer.charStringEncodeBuffer, encodedBlockSize);
|
|
length -= blockSize;
|
|
pData += blockSize;
|
|
}
|
|
}
|
|
return bytesWritten;
|
|
}
|
|
|
|
static void PutStringID(XCF_Handle h, StringID sid)
|
|
{
|
|
char PTR_PREFIX *str;
|
|
Card16 len;
|
|
|
|
XCF_LookUpString(h, sid, &str, &len);
|
|
XT1_PutT1Data(h,(Card8 PTR_PREFIX *)str,len);
|
|
}
|
|
|
|
static void PutString(XCF_Handle h, char PTR_PREFIX *str)
|
|
{
|
|
XT1_PutT1Data(h,(Card8 PTR_PREFIX *)str,h->callbacks.strlen(str));
|
|
}
|
|
|
|
static void PutLine(XCF_Handle h, char PTR_PREFIX *str)
|
|
{
|
|
PutString(h, str);
|
|
PutString(h, XCF_NEW_LINE);
|
|
}
|
|
|
|
static void PutLongNumber(XCF_Handle h, long n)
|
|
{
|
|
char str[30];
|
|
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "%ld", n);
|
|
PutString(h,str);
|
|
}
|
|
|
|
#ifdef XCF_REAL_OK
|
|
static void PutNumber(XCF_Handle h, Fixed n, boolean fracType)
|
|
{
|
|
char str[30];
|
|
|
|
if ((!fracType && (n & 0x0000FFFF) == 0) || (fracType && (n & 0x3FFFFFFF) == 0))
|
|
/* n is an integer */
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "%ld", fracType ? (Int32)FRAC_TO_REAL(n) : (Int32)FIXED_TO_INT(n));
|
|
else
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "%.7g", fracType ? FRAC_TO_REAL(n) : FIXED_TO_REAL(n));
|
|
PutString(h,str);
|
|
}
|
|
|
|
static void PutRoundedFixedNumber(XCF_Handle h, Fixed n)
|
|
{
|
|
char str[30];
|
|
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "%.2f", FIXED_TO_REAL(n));
|
|
PutString(h,str);
|
|
}
|
|
|
|
#else
|
|
|
|
static void PutNumber(XCF_Handle h, Fixed n, boolean fracType)
|
|
{
|
|
char str[30];
|
|
|
|
if ((!fracType && (n & 0x0000FFFF) == 0) || (fracType && (n & 0x3FFFFFFF) == 0))
|
|
/* n is an integer */
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "%ld", fracType ? (Int32)(n >> 30) : (Int32)FIXED_TO_INT(n));
|
|
else
|
|
XCF_Fixed2CString(n, str, 7, fracType);
|
|
PutString(h,str);
|
|
}
|
|
|
|
static void PutRoundedFixedNumber(XCF_Handle h, Fixed n)
|
|
{
|
|
char str[30];
|
|
|
|
XCF_Fixed2CString(n, str, 2, false);
|
|
PutString(h,str);
|
|
}
|
|
#endif /* XCF_REAL_OK */
|
|
|
|
static void StartEexec(XCF_Handle h)
|
|
{
|
|
PutString(h,"currentfile eexec ");
|
|
XCF_FlushOutputBuffer(h);
|
|
h->outBuffer.eexecOn = true;
|
|
h->outBuffer.charsOnLine = INITIAL_CHARS_ON_HEX_LINE;
|
|
h->outBuffer.eexecKey = EEXEC_INITIAL_KEY;
|
|
XT1_PutT1Data(h, h->outBuffer.eexecInitialBytes, 4);
|
|
}
|
|
|
|
static void StopEexec(XCF_Handle h)
|
|
{
|
|
XCF_FlushOutputBuffer(h);
|
|
h->outBuffer.eexecOn = false;
|
|
}
|
|
|
|
static void WriteSIDLine(XCF_Handle h, char *name, Fixed sid, IntX count)
|
|
{
|
|
if (count)
|
|
{
|
|
PutString(h, "/");
|
|
PutString(h, name);
|
|
PutString(h, " (");
|
|
PutStringID(h, (StringID)sid);
|
|
PutString(h, ")" T1_READONLY " def" XCF_NEW_LINE);
|
|
}
|
|
}
|
|
|
|
static void WriteLongNumberLine(XCF_Handle h, char *name, long number, IntX count)
|
|
{
|
|
if (count)
|
|
{
|
|
PutString(h, "/");
|
|
PutString(h, name);
|
|
PutString(h, " ");
|
|
PutLongNumber(h, number);
|
|
PutString(h, " def" XCF_NEW_LINE);
|
|
}
|
|
}
|
|
|
|
static void WriteNumberLine(XCF_Handle h, char *name, Fixed number, IntX count,
|
|
boolean fracType)
|
|
{
|
|
if (count)
|
|
{
|
|
PutString(h, "/");
|
|
PutString(h, name);
|
|
PutString(h, " ");
|
|
PutNumber(h, number, fracType);
|
|
PutString(h, " def" XCF_NEW_LINE);
|
|
}
|
|
}
|
|
|
|
static Fixed PutNumberList(XCF_Handle h, Fixed numbers[], IntX count, boolean
|
|
delta, Fixed initialValue, boolean fracType)
|
|
{
|
|
Fixed number = initialValue;
|
|
Int16 i;
|
|
|
|
for (i=0; i < count; ++i)
|
|
{
|
|
if (delta)
|
|
number += numbers[i];
|
|
else
|
|
number = numbers[i];
|
|
PutNumber(h, number, fracType);
|
|
PutString(h, " ");
|
|
}
|
|
return number;
|
|
}
|
|
|
|
static void PutBlendNumberList(XCF_Handle h, Fixed numbers[], IntX count,
|
|
boolean delta,
|
|
Fixed PTR_PREFIX *pInitialValues,
|
|
IntX iniValCount,
|
|
boolean fracType)
|
|
{
|
|
Fixed number;
|
|
Int16 i;
|
|
|
|
for (i=0; (i < count) && (i < iniValCount); ++i)
|
|
{
|
|
if (delta)
|
|
number = numbers[i] + *pInitialValues;
|
|
else
|
|
number = numbers[i];
|
|
PutNumber(h, number, fracType);
|
|
PutString(h, " ");
|
|
*pInitialValues++ = number;
|
|
}
|
|
}
|
|
|
|
static void PutFontMatrix(XCF_Handle h, char (PTR_PREFIX *list)[FONT_MATRIX_ENTRY_SIZE], IntX count)
|
|
{
|
|
Int16 i;
|
|
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
PutString(h, list[i]);
|
|
PutString(h, " ");
|
|
}
|
|
}
|
|
|
|
static void WriteNumberListLine(XCF_Handle h, char PTR_PREFIX *name, Fixed
|
|
numbers[], IntX count, boolean fracType)
|
|
{
|
|
if (count)
|
|
{
|
|
PutString(h, "/");
|
|
PutString(h, name);
|
|
PutString(h, " [");
|
|
PutNumberList(h, numbers, count, false, 0, fracType);
|
|
PutString(h, "]" T1_READONLY " def" XCF_NEW_LINE);
|
|
}
|
|
}
|
|
|
|
static void WriteLongNumberListLine(XCF_Handle h, char PTR_PREFIX *name, Card32
|
|
numbers[], IntX count)
|
|
{
|
|
Int16 i;
|
|
|
|
if (count)
|
|
{
|
|
PutString(h, "/");
|
|
PutString(h, name);
|
|
PutString(h, " [");
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
PutLongNumber(h, numbers[i]);
|
|
PutString(h, " ");
|
|
}
|
|
PutString(h, "]" T1_READONLY " def" XCF_NEW_LINE);
|
|
}
|
|
}
|
|
|
|
static void WriteFontMatrix(XCF_Handle h, char PTR_PREFIX *name,
|
|
char (PTR_PREFIX *stringList)[FONT_MATRIX_ENTRY_SIZE], IntX count)
|
|
{
|
|
if (count)
|
|
{
|
|
PutString(h, "/");
|
|
PutString(h, name);
|
|
PutString(h, " [");
|
|
PutFontMatrix(h, stringList, count);
|
|
PutString(h, "]" T1_READONLY " def" XCF_NEW_LINE);
|
|
}
|
|
}
|
|
|
|
static Fixed Blend(XCF_Handle h, Fixed numbers[], IntX count, boolean delta,
|
|
Fixed PTR_PREFIX *pInitialValues, IntX iniValCount, boolean fracType)
|
|
{
|
|
Fixed blend = 0;
|
|
Fixed value;
|
|
IntX i;
|
|
|
|
if (count == 1)
|
|
return(numbers[0]);
|
|
else
|
|
{
|
|
if (count != h->dict.numberOfMasters)
|
|
XCF_FATAL_ERROR(h, XCF_InvalidBlendArgumentCount, "Blend argument count does not equal number of masters", count);
|
|
for (i=0; (i < count) && (i < iniValCount) ; ++i)
|
|
{
|
|
if (delta)
|
|
value = numbers[i] + *pInitialValues;
|
|
else
|
|
value = numbers[i];
|
|
blend += fracType? XCF_FracMul(value, h->dict.weightVector[i] << 14) : XCF_FixMul(value, h->dict.weightVector[i]);
|
|
*pInitialValues++ = value;
|
|
}
|
|
}
|
|
return blend;
|
|
}
|
|
|
|
static void PutBlendedNumber(XCF_Handle h, Fixed numbers[], IntX count,
|
|
boolean delta, Fixed PTR_PREFIX *pInitialValues,
|
|
IntX iniValCount, boolean fracType)
|
|
{
|
|
Fixed val = Blend(h, numbers, count, delta, pInitialValues, iniValCount, fracType);
|
|
|
|
if (fracType)
|
|
PutNumber(h, val, true);
|
|
else
|
|
PutRoundedFixedNumber(h, val);
|
|
}
|
|
|
|
static void PutBlend(XCF_Handle h, Fixed numbers[], IntX count, boolean
|
|
instance, boolean squareBrackets, boolean delta, Fixed
|
|
PTR_PREFIX *pInitialValues, IntX iniValCount, boolean fracType)
|
|
{
|
|
IntX i;
|
|
|
|
if (count == 1)
|
|
{
|
|
if ((h->dict.numberOfMasters == 0) || (instance))
|
|
PutNumber(h, numbers[0], fracType);
|
|
else /* expand single value to number of masters */
|
|
{
|
|
PutString(h, squareBrackets ? "[ " : "{ ");
|
|
for (i = 0; i < h->dict.numberOfMasters; ++i)
|
|
{
|
|
PutNumber(h, numbers[0], fracType);
|
|
PutString(h, " ");
|
|
}
|
|
PutString(h, squareBrackets ? "]" : "}");
|
|
}
|
|
}
|
|
else if (instance)
|
|
{
|
|
PutBlendedNumber(h, numbers, count, delta, pInitialValues, iniValCount, fracType);
|
|
}
|
|
else
|
|
{
|
|
PutString(h, squareBrackets ? "[ " : "{ ");
|
|
PutBlendNumberList(h, numbers, count, delta, pInitialValues, iniValCount, fracType);
|
|
PutString(h, squareBrackets ? "]" : "}");
|
|
}
|
|
}
|
|
|
|
static void WriteBlendLine(XCF_Handle h, char PTR_PREFIX *name, Fixed
|
|
numbers[], IntX count, boolean instance, boolean
|
|
squareBrackets, boolean delta, boolean fracType)
|
|
{
|
|
Fixed previousValues[MAX_RASTERIZER_STACK_SIZE] = {0};
|
|
|
|
if (count)
|
|
{
|
|
PutString(h, "/");
|
|
PutString(h, name);
|
|
PutString(h, " ");
|
|
PutBlend(h, numbers, count, instance, squareBrackets, delta,
|
|
&previousValues[0],
|
|
sizeof(previousValues)/sizeof(Fixed), fracType);
|
|
PutString(h, " def" XCF_NEW_LINE);
|
|
}
|
|
}
|
|
|
|
static void PutBlendArray(XCF_Handle h, Fixed numbers[], IntX count, boolean
|
|
instance, boolean squareBrackets, boolean delta,
|
|
boolean fracType)
|
|
{
|
|
IntX blendCount;
|
|
IntX i;
|
|
Fixed previousValues[MAX_RASTERIZER_STACK_SIZE] = {0};
|
|
|
|
if (h->dict.numberOfMasters == 0)
|
|
PutNumberList(h, numbers, count, delta, 0, fracType);
|
|
else
|
|
{
|
|
blendCount = (IntX) (count / h->dict.numberOfMasters);
|
|
for (i = 0; i < blendCount; ++i)
|
|
{
|
|
PutBlend(h, &numbers[i*h->dict.numberOfMasters], h->dict.numberOfMasters,
|
|
instance, squareBrackets, delta, &previousValues[0],
|
|
sizeof(previousValues)/sizeof(Fixed), fracType);
|
|
PutString(h, " ");
|
|
}
|
|
}
|
|
}
|
|
|
|
static void WriteBlendArrayLine(XCF_Handle h, char PTR_PREFIX *name, Fixed
|
|
numbers[], IntX count, boolean instance,
|
|
boolean squareBrackets, boolean delta,
|
|
boolean fracType)
|
|
{
|
|
if (count)
|
|
{
|
|
PutString(h, "/");
|
|
PutString(h, name);
|
|
PutString(h, squareBrackets ? " [ " : " { ");
|
|
PutBlendArray(h, numbers, count, instance, squareBrackets, delta, fracType);
|
|
PutString(h, squareBrackets ? "]" : "}");
|
|
PutString(h, " def" XCF_NEW_LINE);
|
|
}
|
|
}
|
|
|
|
|
|
static void PutBoolean(XCF_Handle h, Fixed value)
|
|
{
|
|
if (value)
|
|
PutString(h, "true ");
|
|
else
|
|
PutString(h, "false ");
|
|
}
|
|
|
|
static void PutBlendBoolean(XCF_Handle h, Fixed values[], IntX count, boolean instance, Fixed threshold)
|
|
{
|
|
Fixed blend = 0;
|
|
IntX i;
|
|
|
|
if (count == 1)
|
|
{
|
|
if ((h->dict.numberOfMasters == 0) || (instance))
|
|
PutBoolean(h, values[0]);
|
|
else /* expand single value to number of masters */
|
|
{
|
|
PutString(h, "[ ");
|
|
for (i = 0; i < h->dict.numberOfMasters; ++i)
|
|
PutBoolean(h, values[0]);
|
|
PutString(h, "]");
|
|
}
|
|
}
|
|
else if (instance)
|
|
{
|
|
for (i=0; i < count ; ++i)
|
|
blend += XCF_FixMul(values[i], h->dict.weightVector[i]);
|
|
PutBoolean(h, (blend >= threshold));
|
|
}
|
|
else
|
|
{
|
|
PutString(h, "[ ");
|
|
for (i=0; i < count ; ++i)
|
|
PutBoolean(h, values[i]);
|
|
PutString(h, "]");
|
|
}
|
|
}
|
|
|
|
static char StreamEncodeName(XCF_Handle h)
|
|
{
|
|
if (!h->options.dlOptions.encodeName)
|
|
return 0;
|
|
PutString(h, "/Encoding ");
|
|
PutString(h, (char PTR_PREFIX *)h->options.dlOptions.encodeName);
|
|
PutString(h, " def" XCF_NEW_LINE);
|
|
return 1;
|
|
}
|
|
|
|
static char StreamFontName(XCF_Handle h)
|
|
{
|
|
if (!h->options.dlOptions.fontName)
|
|
return 0;
|
|
PutString(h, (char PTR_PREFIX *)h->options.dlOptions.fontName);
|
|
return 1;
|
|
}
|
|
|
|
static char StreamUID(XCF_Handle h)
|
|
{
|
|
switch (h->options.uniqueIDMethod)
|
|
{
|
|
case XCF_KEEP_UID:
|
|
return 0;
|
|
case XCF_UNDEFINE_UID:
|
|
return 1;
|
|
case XCF_USER_UID:
|
|
WriteLongNumberLine(h, "UniqueID", h->options.uniqueID, 1);
|
|
return 1;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static char StreamKeyPointData(XCF_Handle h, Card16 code)
|
|
{
|
|
switch (code)
|
|
{
|
|
case XCF_ENCODING:
|
|
return StreamEncodeName(h);
|
|
break;
|
|
case XCF_FONTNAME:
|
|
return StreamFontName(h);
|
|
break;
|
|
case XCF_UID:
|
|
return StreamUID(h);
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void WriteBlendBooleanLine(XCF_Handle h, char PTR_PREFIX *name, Fixed values[], IntX count, boolean instance, Fixed threshold)
|
|
{
|
|
if (count)
|
|
{
|
|
PutString(h, "/");
|
|
PutString(h, name);
|
|
PutString(h, " ");
|
|
PutBlendBoolean(h, values, count, instance, threshold);
|
|
PutString(h, " def" XCF_NEW_LINE);
|
|
}
|
|
}
|
|
|
|
#define BLDOTHERSUBRS (5) /* Number of OtherSubrs specific to mmfonts. */
|
|
|
|
static void WriteRoll(XCF_Handle h, int m, int n)
|
|
{
|
|
char str[50];
|
|
|
|
if (m < 2 || n == 0 || n == m)
|
|
return;
|
|
if (m == 2 && (n == 1 || n == -1))
|
|
{
|
|
PutString(h, "exch ");
|
|
return;
|
|
}
|
|
if (n < 0 && m + n <= -n)
|
|
n = m + n;
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "%ld %ld roll ", m, n);
|
|
PutString(h, str);
|
|
}
|
|
|
|
/* Writes the PS code for OtherSubrs 14 - 18, if necessary. If
|
|
this OtherSubr is unnecessary, i.e. the # of masters times
|
|
the # of results exceeds the font stack limit then no more
|
|
OtherSubrs are written out. */
|
|
static void WriteBlendOtherSubrs(XCF_Handle h)
|
|
{
|
|
int i = 0;
|
|
int j;
|
|
int resultCt[BLDOTHERSUBRS]; /* Number of results after blending */
|
|
int numOutput = 0;
|
|
|
|
resultCt[i++] = 1;
|
|
resultCt[i++] = 2;
|
|
resultCt[i++] = 3;
|
|
resultCt[i++] = 4;
|
|
resultCt[i++] = 6;
|
|
for (i = 0; i < BLDOTHERSUBRS; i++)
|
|
{
|
|
if (h->dict.numberOfMasters * resultCt[i] > T1_MAX_OP_STACK)
|
|
break;
|
|
PutString(h, "{ ");
|
|
for (j = resultCt[i]; j > 1; j--)
|
|
{
|
|
WriteRoll(h, resultCt[i], -1);
|
|
WriteRoll(h, j * (h->dict.numberOfMasters - 1) + resultCt[i], 1 -
|
|
h->dict.numberOfMasters);
|
|
PutString(h, "$Blend ");
|
|
}
|
|
WriteRoll(h, resultCt[i], -1);
|
|
WriteRoll(h, h->dict.numberOfMasters + resultCt[i] - 1,
|
|
-(h->dict.numberOfMasters - 1));
|
|
PutString(h, "$Blend } bind" XCF_NEW_LINE);
|
|
numOutput++;
|
|
}
|
|
/* Make certain that we output up through OtherSubr #18. */
|
|
for (i = numOutput; i < BLDOTHERSUBRS; i++)
|
|
PutString(h, "{}" XCF_NEW_LINE);
|
|
}
|
|
|
|
/* Write the PS code for OtherSubrs 19-27. Currently, these are only
|
|
defined for fonts with transitional designs and are for backward
|
|
compatibility with earlier rasterizers that did not have these
|
|
operators defined. */
|
|
static void WriteAdditionalOtherSubrs(XCF_Handle h)
|
|
{
|
|
/* 19 storeWV */
|
|
PutString(h, "{currentfont dup /WeightVector get exch /Private get /BuildCharArray get 3 -1 roll cvi 3 -1 roll putinterval}" XCF_NEW_LINE);
|
|
/* 20 add */
|
|
PutString(h, "{add}" XCF_NEW_LINE);
|
|
/* 21 sub */
|
|
PutString(h, "{exch sub}" XCF_NEW_LINE);
|
|
/* 22 mul */
|
|
PutString(h, "{mul}" XCF_NEW_LINE);
|
|
/* 23 div */
|
|
PutString(h, "{exch div}" XCF_NEW_LINE);
|
|
/* 24 put */
|
|
PutString(h, "{currentfont /Private get /BuildCharArray get 3 1 roll exch cvi exch put}" XCF_NEW_LINE);
|
|
/* 25 get */
|
|
PutString(h, "{currentfont /Private get /BuildCharArray get exch cvi get }"
|
|
XCF_NEW_LINE);
|
|
/* 26 psput */
|
|
PutString(h, "{exch dup mark eq {3 1 roll}{exch} ifelse currentfont /Private get /BuildCharArray get 3 1 roll cvi exch put}" XCF_NEW_LINE);
|
|
/* 27 ifelse */
|
|
PutString(h, "{4 2 roll exch le {exch} if pop}" XCF_NEW_LINE);
|
|
}
|
|
|
|
static void WriteOtherSubrs(XCF_Handle h, boolean flexUsed, boolean hintSubUsed)
|
|
{
|
|
/* Check if the client requests to use special names for OtherSubrs 0-3. */
|
|
if ( h->options.dlOptions.otherSubrNames )
|
|
{
|
|
unsigned short i;
|
|
|
|
PutString(h, "/OtherSubrs [" XCF_NEW_LINE);
|
|
for ( i = 0; i < 4; i++ )
|
|
{
|
|
PutString(h, "{");
|
|
#if HAS_COOLTYPE_UFL == 1
|
|
PutString(h, "ct_CffDict/");
|
|
#endif
|
|
if ( h->options.dlOptions.otherSubrNames[i] )
|
|
{
|
|
PutString(h, (char PTR_PREFIX *)h->options.dlOptions.otherSubrNames[i]);
|
|
#if HAS_COOLTYPE_UFL == 1
|
|
PutString(h, " get exec");
|
|
#endif
|
|
PutString(h, "}executeonly");
|
|
}
|
|
else
|
|
{
|
|
PutString(h, "}");
|
|
}
|
|
}
|
|
if (h->dict.numberOfMasters)
|
|
{
|
|
PutString(h, "{} {} {}" XCF_NEW_LINE); /* 4-6 */
|
|
PutString(h, "{} {} {} {} {} {} {} " XCF_NEW_LINE); /* 7-13 */
|
|
WriteBlendOtherSubrs(h); /* 14-18 */
|
|
if (XCF_TransDesignFont(h))
|
|
WriteAdditionalOtherSubrs(h); /* 19-27 */
|
|
}
|
|
|
|
PutString(h, "] |-" XCF_NEW_LINE);
|
|
return;
|
|
}
|
|
|
|
if (flexUsed || hintSubUsed || h->dict.numberOfMasters)
|
|
{
|
|
PutString(h, "/OtherSubrs" XCF_NEW_LINE);
|
|
if (flexUsed)
|
|
{
|
|
PutString(h, FlexOtherSubrStr1);
|
|
PutString(h, FlexOtherSubrStr2);
|
|
PutString(h, FlexOtherSubrStr3);
|
|
PutString(h, FlexOtherSubrStr4);
|
|
PutString(h, FlexOtherSubrStr5);
|
|
PutString(h, FlexOtherSubrStr6);
|
|
PutString(h, FlexOtherSubrStr7);
|
|
PutString(h, FlexOtherSubrStr8);
|
|
PutString(h, FlexOtherSubrStr9);
|
|
PutString(h, FlexOtherSubrStr10);
|
|
PutString(h, FlexOtherSubrStr11);
|
|
PutString(h, FlexOtherSubrStr12);
|
|
PutString(h, FlexOtherSubrStr13);
|
|
PutString(h, FlexOtherSubrStr14);
|
|
PutString(h, FlexOtherSubrStr15);
|
|
PutString(h, FlexOtherSubrStr16);
|
|
PutString(h, FlexOtherSubrStr17);
|
|
}
|
|
else
|
|
{
|
|
PutString(h, "[ {} {} {}" XCF_NEW_LINE);
|
|
}
|
|
|
|
if (hintSubUsed)
|
|
{
|
|
PutString(h, HintSubtitutionOtherSubrStr);
|
|
}
|
|
else
|
|
{
|
|
PutString(h, "{}" XCF_NEW_LINE); /* 3 */
|
|
}
|
|
|
|
PutString(h, "{} {} {}" XCF_NEW_LINE); /* 4-6 */
|
|
|
|
if (h->dict.numberOfMasters)
|
|
{
|
|
PutString(h, "{} {} {} {} {} {} {} " XCF_NEW_LINE); /* 7-13 */
|
|
WriteBlendOtherSubrs(h); /* 14-18 */
|
|
if (XCF_TransDesignFont(h))
|
|
WriteAdditionalOtherSubrs(h); /* 19-27 */
|
|
}
|
|
PutString(h, "]|-" XCF_NEW_LINE);
|
|
}
|
|
}
|
|
|
|
static void WriteCIDOtherSubrs(XCF_Handle h)
|
|
{
|
|
PutLine(h, XCF_NEW_LINE "/OtherSubrs [ {} {} {} { systemdict /internaldict known not" XCF_NEW_LINE
|
|
"{ pop 3 } { 1183615869 systemdict /internaldict get exec dup" XCF_NEW_LINE
|
|
"/startlock known { /startlock get exec }" XCF_NEW_LINE
|
|
"{ dup /strtlck known { /strtlck get exec } { pop 3 } ifelse } ifelse } ifelse } bind" XCF_NEW_LINE
|
|
"{} {} {} {} {} {} {} {} {}" XCF_NEW_LINE
|
|
"{ 2 {cvi { { pop 0 lt { exit } if } loop } repeat } repeat } bind" XCF_NEW_LINE
|
|
"{} {} {} {} {} {} {} {} {} {} {} {} {} {} {} ] def");
|
|
}
|
|
|
|
static void PutCharacterName(XCF_Handle h, CardX index,
|
|
unsigned char PTR_PREFIX **pGlyphName)
|
|
{
|
|
if (pGlyphName)
|
|
PutString(h, (char PTR_PREFIX *)pGlyphName[index]);
|
|
else
|
|
{
|
|
if (index)
|
|
PutStringID(h, h->type1.pCharset[index-1]);
|
|
else
|
|
PutStringID(h, 0);
|
|
}
|
|
}
|
|
|
|
static void PutFontName(XCF_Handle h)
|
|
{
|
|
if (!StreamKeyPointData(h, XCF_FONTNAME))
|
|
{
|
|
XCF_LookUpTableEntry(h, &h->fontSet.fontNames, h->fontSet.fontIndex);
|
|
XT1_PutT1Data(h,(Card8 PTR_PREFIX *)h->inBuffer.start, (Card16)h->inBuffer.blockLength);
|
|
}
|
|
}
|
|
|
|
/*
|
|
Dictionary Entries
|
|
|
|
*** Font Info Dict ***
|
|
|
|
version
|
|
Notice
|
|
FullName
|
|
FamilyName
|
|
Weight
|
|
isFixedPitch Default = "false"
|
|
ItalicAngle Default = 0
|
|
UnderlinePosition Default = -100
|
|
UnderlineThickness Default = 50
|
|
Copyright
|
|
SyntheticBase
|
|
BaseFontName
|
|
BaseFontBlend
|
|
|
|
*** Font Dict ***
|
|
|
|
FontName
|
|
Encoding Default = StandardEncoding
|
|
PaintType Default = 0
|
|
FontType
|
|
FontMatrix Default = [0.001 0 0 0.001 0 0]
|
|
FontBBox
|
|
UniqueID
|
|
XUID
|
|
StrokeWidth Default = 0
|
|
Private
|
|
CharStrings
|
|
BlendDesignMap
|
|
BlendAxisTypes
|
|
WeightVector
|
|
|
|
*** Private Dict ***
|
|
|
|
BlueValues Default = [] -- Emit empty brackets if there are no BlueValues
|
|
OtherBlues
|
|
FamilyBlues
|
|
FamilyOtherBlues
|
|
StdHW
|
|
StdVW
|
|
BlueScale Default = 0.039625
|
|
BlueShift Default = 7
|
|
BlueFuzz Default = 1
|
|
StemSnapH
|
|
StemSnapV
|
|
ForceBold Default = "false"
|
|
ForceBoldThreshold Default = 0
|
|
lenIV
|
|
LanguageGroup Default = 0
|
|
ExpansionFactor Default = 0.06
|
|
initialRandomSeed Default = 0
|
|
PostScript
|
|
defaultWidthX
|
|
nominalWidthX
|
|
NDV
|
|
CDV
|
|
lenBuildCharArray
|
|
*/
|
|
|
|
static boolean GlyphInCharSet(XCF_Handle h, StringID sid)
|
|
{
|
|
CardX i;
|
|
|
|
for (i=0; i < h->type1.charsetSize; ++i)
|
|
if (sid == h->type1.pCharset[i])
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
static void WriteEncodingArray(XCF_Handle h)
|
|
{
|
|
char str[50];
|
|
CardX i;
|
|
|
|
if (h->options.dlOptions.notdefEncoding)
|
|
{
|
|
PutString(h, "/Encoding 256 array" XCF_NEW_LINE);
|
|
PutString(h, "0 1 255 {1 index exch /.notdef put} for");
|
|
#if HAS_COOLTYPE_UFL == 1
|
|
/* If this font needs to be parsed by CoolType or ATM then the
|
|
* Encoding array needs to explicitly define at least one
|
|
* encoding via the dup <charcode>/<name> put format.
|
|
*/
|
|
PutString(h, XCF_NEW_LINE);
|
|
PutString(h, "dup 0 /.notdef put" XCF_NEW_LINE);
|
|
PutString(h, T1_READONLY " def" XCF_NEW_LINE);
|
|
#else
|
|
PutString(h, " def" XCF_NEW_LINE);
|
|
#endif
|
|
return;
|
|
}
|
|
if ((!h->dict.encodingCount) || (h->dict.encoding == cff_StandardEncoding))
|
|
PutString(h, "/Encoding StandardEncoding def" XCF_NEW_LINE);
|
|
else
|
|
{
|
|
PutString(h, "/Encoding 256 array" XCF_NEW_LINE);
|
|
PutString(h, "0 1 255 {1 index exch /.notdef put} for" XCF_NEW_LINE);
|
|
for (i=0;i<256;++i)
|
|
{
|
|
if (h->type1.pEncoding[i] != NOTDEF_SID)
|
|
{
|
|
if ((h->dict.encoding != cff_ExpertEncoding) || GlyphInCharSet(h, h->type1.pEncoding[i]))
|
|
{
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "dup %ld /",(long int)i);
|
|
PutString(h, str);
|
|
PutStringID(h, h->type1.pEncoding[i]);
|
|
PutString(h," put" XCF_NEW_LINE);
|
|
}
|
|
}
|
|
}
|
|
PutString(h, T1_READONLY " def" XCF_NEW_LINE);
|
|
}
|
|
}
|
|
|
|
static void WriteBlendAxisTypes(XCF_Handle h)
|
|
{
|
|
IntX i;
|
|
if (!h->dict.blendAxisTypesCount)
|
|
return;
|
|
|
|
PutString(h, "/BlendAxisTypes [");
|
|
for (i=0;i<h->dict.blendAxisTypesCount;++i)
|
|
{
|
|
PutString(h, "/");
|
|
PutStringID(h, (StringID)h->dict.blendAxisTypes[i]);
|
|
PutString(h, " ");
|
|
}
|
|
PutString(h, "] def" XCF_NEW_LINE);
|
|
}
|
|
|
|
|
|
static CardX FontInfoDictCount(XCF_Handle h)
|
|
{
|
|
CardX count = 5; /* Add extra space for safety margin */
|
|
|
|
count += (h->dict.noticeCount != 0);
|
|
count += (h->dict.copyrightCount != 0);
|
|
count += (h->dict.versionCount != 0);
|
|
count += (h->dict.fullNameCount != 0);
|
|
count += (h->dict.familyNameCount != 0);
|
|
count += (h->dict.baseFontNameCount != 0);
|
|
count += (h->dict.baseFontBlendCount != 0);
|
|
count += (h->dict.weightCount != 0);
|
|
count += (h->dict.italicAngleCount != 0);
|
|
count += (h->dict.isFixedPitchCount != 0);
|
|
count += (h->dict.underlinePositionCount != 0);
|
|
count += (h->dict.underlineThicknessCount != 0);
|
|
count += (h->dict.blendAxisTypesCount != 0);
|
|
count += (h->callbacks.getFSType != 0);
|
|
if (h->dict.numberOfMasters != 0)
|
|
count += 4; /* Add for /DesignVector, /NormDesignVector,
|
|
* /BlendDesignPositions, and /BlendDesignMap */
|
|
return count;
|
|
}
|
|
|
|
static CardX FontDictCount(XCF_Handle h)
|
|
{
|
|
CardX count;
|
|
|
|
/* Add extra space for FontName, Encoding, FontType, etc. plus safety margin.
|
|
* For mm fonts enough space is added for all of the extra mm definitions */
|
|
count = (h->dict.numberOfMasters != 0) ? 25 : 10;
|
|
count += (h->dict.paintTypeCount != 0);
|
|
count += (h->dict.fontMatrixCount != 0);
|
|
count += (h->dict.fontBBoxCount != 0);
|
|
count += (h->dict.uniqueIDCount != 0);
|
|
count += (h->dict.xUIDCount != 0);
|
|
count += (h->dict.strokeWidthCount != 0);
|
|
return count;
|
|
}
|
|
|
|
static CardX PrivateDictCount(XCF_Handle h)
|
|
{
|
|
CardX count = 15; /* Add extra space for LenIV, MinFeature, password, Erode, OtherSubrs, Subr, etc. plus safety margin */
|
|
|
|
count += (h->dict.uniqueIDCount != 0);
|
|
count += (h->dict.blueValuesCount != 0);
|
|
count += (h->dict.otherBluesCount != 0);
|
|
count += (h->dict.familyBluesCount != 0);
|
|
count += (h->dict.familyOtherBluesCount != 0);
|
|
count += (h->dict.stdHWCount != 0);
|
|
count += (h->dict.stdVWCount != 0);
|
|
count += (h->dict.blueScaleCount != 0);
|
|
count += (h->dict.blueShiftCount != 0);
|
|
count += (h->dict.blueFuzzCount != 0);
|
|
count += (h->dict.stemSnapHCount != 0);
|
|
count += (h->dict.stemSnapVCount != 0);
|
|
count += (h->dict.forceBoldCount != 0);
|
|
count += (h->dict.forceBoldThresholdCount != 0);
|
|
count += (h->dict.languageGroupCount != 0);
|
|
count += (h->dict.expansionFactorCount != 0);
|
|
count += (h->dict.initialRandomSeedCount != 0);
|
|
if (h->options.outputCharstrType != 1)
|
|
{
|
|
count += (h->dict.defaultWidthXCount != 0);
|
|
count += (h->dict.nominalWidthXCount != 0);
|
|
}
|
|
if (h->dict.lenBuildCharArrayCount != 0)
|
|
count += 2; /* Add extra one for /BuildCharArray */
|
|
if (h->dict.numberOfMasters > 0)
|
|
count += 2; /* Add 2 for NDV and CDV */
|
|
count += (h->dict.embeddedPostscriptCount != 0);
|
|
#ifdef T13
|
|
if (XT13_IST13(h))
|
|
count++;
|
|
#endif
|
|
|
|
return count;
|
|
}
|
|
|
|
static void WriteBlendProc(XCF_Handle h)
|
|
{
|
|
IntX vectorIndex;
|
|
|
|
if (h->dict.numberOfMasters == 0)
|
|
return;
|
|
PutString(h, "/$Blend {");
|
|
for (vectorIndex = 1; vectorIndex < h->dict.numberOfMasters; ++vectorIndex)
|
|
{
|
|
PutRoundedFixedNumber(h, h->dict.weightVector[vectorIndex]);
|
|
PutString(h, " mul ");
|
|
if (vectorIndex > 1)
|
|
PutString(h, "add ");
|
|
if (vectorIndex < h->dict.numberOfMasters - 1)
|
|
PutString(h, "exch ");
|
|
}
|
|
PutString(h, "add } bind def" XCF_NEW_LINE);
|
|
}
|
|
|
|
|
|
#if HAS_COOLTYPE_UFL == 1
|
|
static void WriteBlendDict(XCF_Handle h)
|
|
{
|
|
PutString(h, "/Blend 3 dict dup begin" XCF_NEW_LINE );
|
|
WriteBlendArrayLine(h, "FontBBox", h->dict.fontBBox, h->dict.fontBBoxCount,
|
|
false, false, false, false);
|
|
PutString(h, "/FontInfo 3 dict dup begin" XCF_NEW_LINE);
|
|
WriteBlendLine(h, "ItalicAngle", h->dict.italicAngle,
|
|
h->dict.italicAngleCount, false, true, true, false);
|
|
WriteBlendLine(h, "UnderlinePosition", h->dict.underlinePosition,
|
|
h->dict.underlinePositionCount, false, true, true, false);
|
|
WriteBlendLine(h, "UnderlineThickness", h->dict.underlineThickness,
|
|
h->dict.underlineThicknessCount, false, true, true, false);
|
|
PutString(h, "end def" XCF_NEW_LINE);
|
|
PutString(h, "/Private 14 dict def" XCF_NEW_LINE "end def" XCF_NEW_LINE);
|
|
}
|
|
|
|
static void WriteMakeBlendedFontOp(XCF_Handle h)
|
|
{
|
|
#include "xcf_mkbf.h"
|
|
}
|
|
|
|
static void WriteInterpCharString(XCF_Handle h)
|
|
{
|
|
boolean unprocessed = h->options.outputCharstrType == 2;
|
|
|
|
#include "xcf_ics.h"
|
|
}
|
|
|
|
static void WriteMMFindFontDef(XCF_Handle h)
|
|
{
|
|
#include "xcf_mmff.h"
|
|
}
|
|
|
|
/* Writes the multiple master font specific NormalizeDesignVector and
|
|
* ConvertDesignVector procedures.
|
|
*/
|
|
static void WriteDesignVectorProcs(XCF_Handle h)
|
|
{
|
|
char icsmemname[128];
|
|
char icsflagname[128];
|
|
char str[128];
|
|
char fontName[512];
|
|
Card32 subrNum = h->options.outputCharstrType == 1 ?
|
|
h->type1.subrOffsets.cnt : h->dict.localSubrs.count;
|
|
|
|
if (h->options.dlOptions.fontName)
|
|
{
|
|
unsigned short int length = sizeof(fontName);
|
|
/* add 1 for null terminator */
|
|
if (length > (unsigned short int)(h->callbacks.strlen((const char PTR_PREFIX *)h->options.dlOptions.fontName) + 1))
|
|
length = (unsigned short int)(h->callbacks.strlen((const char PTR_PREFIX *)h->options.dlOptions.fontName) + 1);
|
|
h->callbacks.memcpy(fontName, h->options.dlOptions.fontName, length);
|
|
}
|
|
else
|
|
XCF_FontName(h, (unsigned short int)h->fontSet.fontIndex, fontName,
|
|
(unsigned short int)(sizeof(fontName)));
|
|
h->callbacks.xcfSprintf(icsmemname, CCHOF(icsmemname), "&%sicsmem", fontName);
|
|
h->callbacks.xcfSprintf(icsflagname, CCHOF(icsflagname), "&%sflag", fontName);
|
|
PutString(h, "/ICSsetup {" XCF_NEW_LINE);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "userdict /%s known not {%s", icsmemname,
|
|
XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " userdict /%s 25 dict put%s", icsmemname,
|
|
XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " userdict /%s get /&thisfontdict currentdict put%s", icsmemname, XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " userdict /%s get /:savestack 10 array put%s",
|
|
icsmemname, XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " userdict /%s get /:savelevel 0 put%s",
|
|
icsmemname, XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " userdict /%s get dup /&me exch put%s",
|
|
icsmemname, XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " userdict /%s get /WeightVector known not {%s",
|
|
icsmemname, XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " userdict /%s get /WeightVector %d array put%s", icsmemname, h->dict.numberOfMasters, XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " userdict /%s get /NormDesignVector %d array put%s", icsmemname, h->dict.userDesignVectorCount, XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " userdict /%s get /DesignVector %d array put%s", icsmemname, h->dict.userDesignVectorCount, XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
PutString(h, " } if" XCF_NEW_LINE);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " userdict /%s get {%s", icsflagname, XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " currentdict /WeightVector get aload pop userdict /%s", icsmemname);
|
|
PutString(h, str);
|
|
PutString(h, " get /WeightVector get astore pop" XCF_NEW_LINE);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " currentdict /NormDesignVector get aload pop userdict /%s", icsmemname);
|
|
PutString(h, str);
|
|
PutString(h, " get /NormDesignVector get astore pop" XCF_NEW_LINE);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " currentdict /DesignVector get aload pop userdict /%s", icsmemname);
|
|
PutString(h, str);
|
|
PutString(h, " get /DesignVector get astore pop" XCF_NEW_LINE);
|
|
PutString(h, " } if" XCF_NEW_LINE);
|
|
PutString(h, "} if } bind def" XCF_NEW_LINE);
|
|
PutString(h, "/Pre-N&C {" XCF_NEW_LINE);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " userdict /%s known not {userdict /%s true put}%s", icsflagname, icsflagname, XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " {/%s true store} ifelse%s", icsflagname,
|
|
XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
PutString(h, "} bind def" XCF_NEW_LINE);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "/Post-N&C {/%s false store} bind def%s",
|
|
icsflagname, XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
|
|
/* Write NormalizeDesignVector procedure. */
|
|
PutString(h, "/NormalizeDesignVector {" XCF_NEW_LINE);
|
|
PutString(h, "Pre-N&C ICSsetup" XCF_NEW_LINE);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "%s /DesignVector get astore pop%s", icsmemname,
|
|
XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "%d %s interpcharstring%s", (IntX) subrNum, icsmemname, XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "%s /NormDesignVector get aload pop ", icsmemname);
|
|
PutString(h, str);
|
|
PutString(h, XCF_NEW_LINE "} bind def" XCF_NEW_LINE);
|
|
|
|
/* Write ConvertDesignVector procedure. */
|
|
PutString(h, "/ConvertDesignVector {" XCF_NEW_LINE);
|
|
PutString(h, "Pre-N&C ICSsetup" XCF_NEW_LINE);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "%s /NormDesignVector get astore pop%s",
|
|
icsmemname, XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "%d %s interpcharstring%s",
|
|
(IntX) subrNum + 1, icsmemname, XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
PutString(h, "Post-N&C" XCF_NEW_LINE);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "%s /WeightVector get aload pop ", icsmemname);
|
|
PutString(h, str);
|
|
PutString(h, XCF_NEW_LINE "} bind def" XCF_NEW_LINE);
|
|
}
|
|
#endif /* HAS_COOLTYPE_UFL */
|
|
|
|
static void PutStemSnapBugFix(XCF_Handle h, Fixed arg1, Fixed numbers[], IntX count)
|
|
{
|
|
Fixed arg2 = 0;
|
|
IntX i;
|
|
|
|
for (i=0; i < count; ++i)
|
|
arg2 += numbers[i];
|
|
|
|
PutString(h, XCF_NEW_LINE " systemdict /internaldict known" XCF_NEW_LINE "{1183615869 systemdict /internaldict get exec" XCF_NEW_LINE "/StemSnapLength 2 copy known {get ");
|
|
PutLongNumber(h, count);
|
|
PutString(h, " lt} {pop pop true} ifelse}" XCF_NEW_LINE "{true} ifelse {pop [");
|
|
PutNumber(h, arg1, false);
|
|
PutString(h, " ");
|
|
PutNumber(h, arg2, false);
|
|
PutString(h, "]} if def" XCF_NEW_LINE);
|
|
}
|
|
|
|
static void WriteStemSnap(XCF_Handle h, boolean instance)
|
|
{
|
|
WriteBlendArrayLine(h, "StdHW", h->dict.stdHW, h->dict.stdHWCount, instance,
|
|
true, true, false);
|
|
WriteBlendArrayLine(h, "StdVW", h->dict.stdVW, h->dict.stdVWCount, instance,
|
|
true, true, false);
|
|
if (h->dict.stemSnapHCount)
|
|
{
|
|
PutString(h, "/StemSnapH [ ");
|
|
PutBlendArray(h, h->dict.stemSnapH, h->dict.stemSnapHCount, instance, true,
|
|
true, false);
|
|
PutString(h, "] ");
|
|
if ((h->dict.stemSnapHCount > 2) && (!h->dict.numberOfMasters))/* xxx fix stem snap bug fix to work for MM */
|
|
PutStemSnapBugFix(h, h->dict.stdHW[0], h->dict.stemSnapH, h->dict.stemSnapHCount);
|
|
else
|
|
PutString(h, "def" XCF_NEW_LINE);
|
|
}
|
|
if (h->dict.stemSnapVCount)
|
|
{
|
|
PutString(h, "/StemSnapV [ ");
|
|
PutBlendArray(h, h->dict.stemSnapV, h->dict.stemSnapVCount, instance, true,
|
|
true, false);
|
|
PutString(h, "] ");
|
|
if ((h->dict.stemSnapVCount > 2) && (!h->dict.numberOfMasters))/* xxx fix stem snap bug fix to work for MM */
|
|
PutStemSnapBugFix(h, h->dict.stdVW[0], h->dict.stemSnapV, h->dict.stemSnapVCount);
|
|
else
|
|
PutString(h, "def" XCF_NEW_LINE);
|
|
}
|
|
}
|
|
|
|
#define FIXEDEIGHT 0x00080000L
|
|
|
|
static void WriteErode(XCF_Handle h, boolean instance) /* xxx fix to use instance */
|
|
{
|
|
IntX i;
|
|
Fixed value = 0;
|
|
Fixed previousValues[MAX_RASTERIZER_STACK_SIZE] = {0};
|
|
Fixed blend = 0;
|
|
Fixed blendedStdVW = Blend(h, h->dict.stdVW, h->dict.stdVWCount, true,
|
|
&previousValues[0],
|
|
sizeof(previousValues)/sizeof(Fixed), false);
|
|
|
|
if ((h->dict.stdVWCount) && (h->dict.stdVW[0] != 0))
|
|
{
|
|
PutString(h,"/Erode{" XCF_NEW_LINE);
|
|
if (!h->dict.numberOfMasters)
|
|
PutNumber(h, XCF_FixDiv(h->dict.stdVW[0],FIXEDEIGHT), false); /* trunc(stdvw/8) + 0.5 */
|
|
else if (instance)
|
|
{
|
|
for (i = 0; i < h->dict.stdVWCount; ++i)
|
|
{
|
|
value = h->dict.stdVW[i];
|
|
blend += XCF_FixMul(XCF_FixDiv(value, FIXEDEIGHT), h->dict.weightVector[i]);
|
|
}
|
|
PutNumber(h, blend, false);
|
|
PutString(h, " ");
|
|
}
|
|
|
|
else
|
|
{
|
|
PutString(h, "{ ");
|
|
for (i = 0; i < h->dict.stdVWCount; ++i)
|
|
{
|
|
value = h->dict.stdVW[i];
|
|
PutNumber(h, XCF_FixDiv(value, FIXEDEIGHT), false); /* trunc(stdvw/8) + 0.5 */
|
|
PutString(h, " ");
|
|
}
|
|
PutString(h, "}");
|
|
}
|
|
PutString(h," dup 3 -1 roll 0.1 mul exch 0.5 sub mul cvi sub dup mul" XCF_NEW_LINE);
|
|
|
|
if ((instance) || (!h->dict.numberOfMasters))
|
|
PutNumber(h, blendedStdVW, false);
|
|
else
|
|
{
|
|
PutString(h, "{ ");
|
|
PutNumberList(h, h->dict.stdVW, h->dict.stdVWCount, false, 0, false);
|
|
PutString(h, "}");
|
|
}
|
|
/* PutNumber(h,h->dict.stdVW[0]); */
|
|
PutString(h," 0 dtransform dup mul exch dup mul add" XCF_NEW_LINE "le{pop pop 1.0 1.0}{pop pop 0.0 1.5}ifelse}def" XCF_NEW_LINE);
|
|
}
|
|
}
|
|
|
|
static void WritePrivateBlendDict(XCF_Handle h)
|
|
{
|
|
if (h->dict.numberOfMasters == 0)
|
|
return;
|
|
|
|
PutString(h, "3 index /Blend get /Private get begin" XCF_NEW_LINE );
|
|
WriteBlendArrayLine(h, "BlueValues", h->dict.blueValues,
|
|
h->dict.blueValuesCount, false, true, true, false);
|
|
WriteBlendArrayLine(h, "OtherBlues", h->dict.otherBlues,
|
|
h->dict.otherBluesCount, false, true, true, false);
|
|
WriteBlendLine(h, "BlueScale", h->dict.blueScale, h->dict.blueScaleCount,
|
|
false, true, true, true);
|
|
WriteBlendLine(h, "BlueShift", h->dict.blueShift, h->dict.blueShiftCount,
|
|
false, true, true, false);
|
|
WriteBlendArrayLine(h, "FamilyBlues", h->dict.familyBlues,
|
|
h->dict.familyBluesCount, false, true, true, false);
|
|
WriteBlendArrayLine(h, "FamilyOtherBlues", h->dict.familyOtherBlues,
|
|
h->dict.familyOtherBluesCount, false, true, true, false);
|
|
WriteBlendBooleanLine(h, "ForceBold", h->dict.forceBold, h->dict.forceBoldCount, false, h->dict.forceBoldThreshold);
|
|
WriteStemSnap(h, false);
|
|
WriteErode(h, false);
|
|
PutString(h, "end" XCF_NEW_LINE );
|
|
|
|
}
|
|
/*
|
|
3 index /Blend get /Private get begin
|
|
/BlueValues[[ -18 -25][ 0 0][ 528 532][ 553 557][ 430 432][ 450 457][ 520 516][ 521 524][ 563 588][ 588 607][ 605 627][ 612 638]] def
|
|
/OtherBlues[[ 252 263][ 259 268][ -144 -168][ -121 -143][ -85 -114][ -68 -105]] def
|
|
/FamilyBlues[[ -18 -18][ 0 0][ 528 528][ 553 553][ 430 430][ 450 450][ 520 520][ 521 521][ 563 563][ 588 588][ 605 605][ 612 612]] def
|
|
/FamilyOtherBlues[[ 252 252][ 259 259][ -144 -144][ -121 -121][ -85 -85][ -68 -68]] def
|
|
/ForceBold [ false true] def
|
|
/StdHW [[25 60 ]] def
|
|
/StdVW [[45 140 ]] def
|
|
/Erode{
|
|
{5.5 17.5 } dup 3 -1 roll 0.1 mul exch 0.5 sub mul cvi sub dup mul
|
|
{45 140 } 0 dtransform dup mul exch dup mul add
|
|
le{pop pop 1.0 1.0}{pop pop 0.0 1.5}ifelse}def
|
|
end
|
|
|
|
/Erode{
|
|
8.166522 dup 3 -1 roll 0.1 mul exch 0.5 sub mul cvi sub dup mul
|
|
66.11 0 dtransform dup mul exch dup mul add
|
|
le{pop pop 1.0 1.0}{pop pop 0.0 1.5}ifelse}def
|
|
|
|
*/
|
|
|
|
static void WriteFontDict(XCF_Handle h)
|
|
{
|
|
char line[MAX_LINE_LENGTH];
|
|
|
|
/* Note: for ATM compatibility
|
|
* for mm fonts the BlendDict must come after the BlendDesignPositions,
|
|
* BlendDesignMap, and BlendAxisTypes definitions.
|
|
*/
|
|
|
|
PutString(h, "%!FontType1" XCF_NEW_LINE);
|
|
|
|
/**** Start Font & FontInfo Dicts ****/
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "%ld dict begin" XCF_NEW_LINE "/FontInfo %ld dict dup begin" XCF_NEW_LINE, (Card32) FontDictCount(h), (Card32) FontInfoDictCount(h));
|
|
PutString(h,line);
|
|
|
|
/**** Write Info Dict ****/
|
|
|
|
WriteSIDLine(h, "Notice", h->dict.notice, h->dict.noticeCount);
|
|
WriteSIDLine(h, "Copyright", h->dict.copyright, h->dict.copyrightCount);
|
|
WriteSIDLine(h, "version", h->dict.version, h->dict.versionCount);
|
|
WriteSIDLine(h, "FullName", h->dict.fullName, h->dict.fullNameCount);
|
|
WriteSIDLine(h, "FamilyName", h->dict.familyName, h->dict.familyNameCount);
|
|
WriteSIDLine(h, "BaseFontName", h->dict.baseFontName, h->dict.baseFontNameCount);
|
|
WriteNumberListLine(h, "BaseFontBlend", h->dict.baseFontBlend,
|
|
h->dict.baseFontBlendCount, false);
|
|
WriteSIDLine(h, "Weight", h->dict.weight, h->dict.weightCount);
|
|
WriteBlendLine(h, "ItalicAngle", h->dict.italicAngle,
|
|
h->dict.italicAngleCount, true, true, true, false);
|
|
WriteBlendBooleanLine(h, "isFixedPitch", h->dict.isFixedPitch, h->dict.isFixedPitchCount, true, FIXEDHALF); /* xxx What do we use for threshold? */
|
|
WriteBlendLine(h, "UnderlinePosition", h->dict.underlinePosition,
|
|
h->dict.underlinePositionCount, true, true, true, false);
|
|
WriteBlendLine(h, "UnderlineThickness", h->dict.underlineThickness,
|
|
h->dict.underlineThicknessCount, true, true, true, false);
|
|
|
|
if (h->callbacks.getFSType)
|
|
{
|
|
long fsType;
|
|
|
|
h->callbacks.getFSType(h, &fsType, h->callbacks.getFSTypeHook);
|
|
if (fsType != -1)
|
|
WriteLongNumberLine(h, "FSType", fsType, 1);
|
|
}
|
|
|
|
if (h->dict.numberOfMasters != 0)
|
|
{
|
|
#if HAS_COOLTYPE_UFL == 1
|
|
if (h->callbacks.getDesignPositions)
|
|
{
|
|
char *bdp;
|
|
|
|
h->callbacks.getDesignPositions(h, &bdp, h->callbacks.getDesignPositionsHook);
|
|
if (bdp[0] != 0)
|
|
{
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "/BlendDesignPositions %s def" XCF_NEW_LINE, bdp);
|
|
PutString(h, line);
|
|
}
|
|
}
|
|
if (h->callbacks.getDesignMap)
|
|
{
|
|
char *bdm;
|
|
|
|
h->callbacks.getDesignMap(h, &bdm, h->callbacks.getDesignMapHook);
|
|
if (bdm[0] != 0)
|
|
{
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "/BlendDesignMap %s def" XCF_NEW_LINE, bdm);
|
|
PutString(h, line);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
WriteBlendAxisTypes(h);
|
|
}
|
|
|
|
PutString(h,"end" T1_READONLY " def" XCF_NEW_LINE); /* end of FontInfo dict*/
|
|
|
|
/**** Write Font Dict ****/
|
|
|
|
PutString(h, "/FontName /");
|
|
PutFontName(h);
|
|
PutString(h, " def" XCF_NEW_LINE);
|
|
if (!StreamKeyPointData(h, XCF_ENCODING))
|
|
WriteEncodingArray(h);
|
|
WriteNumberLine(h, "PaintType", h->dict.paintType, h->dict.paintTypeCount, false);
|
|
WriteLongNumberLine(h, "FontType", h->options.outputCharstrType, 1);
|
|
WriteNumberListLine(h, "DesignVector", h->dict.userDesignVector,
|
|
h->dict.userDesignVectorCount, false);
|
|
WriteNumberListLine(h, "NormDesignVector", h->dict.normDesignVector,
|
|
h->dict.normDesignVectorCount, false);
|
|
WriteNumberListLine(h, "WeightVector", h->dict.weightVector,
|
|
h->dict.numberOfMasters, false);
|
|
WriteBlendProc(h);
|
|
WriteFontMatrix(h, "FontMatrix", h->dict.fontMatrix, h->dict.fontMatrixCount);
|
|
WriteBlendArrayLine(h, "FontBBox", h->dict.fontBBox,
|
|
h->dict.fontBBoxCount, true, false, false, false);
|
|
|
|
#if HAS_COOLTYPE_UFL == 1
|
|
if (h->dict.numberOfMasters != 0)
|
|
{
|
|
WriteBlendDict(h);
|
|
WriteMakeBlendedFontOp(h);
|
|
WriteInterpCharString(h);
|
|
WriteDesignVectorProcs(h);
|
|
WriteMMFindFontDef(h);
|
|
}
|
|
#endif
|
|
|
|
if (!StreamKeyPointData(h, XCF_UID))
|
|
WriteLongNumberLine(h, "UniqueID", h->dict.uniqueID,
|
|
h->dict.uniqueIDCount);
|
|
if (h->dict.xUIDCount > 0)
|
|
WriteLongNumberListLine(h, "XUID", h->dict.xUID, h->dict.xUIDCount);
|
|
WriteBlendLine(h, "StrokeWidth", h->dict.strokeWidth,
|
|
h->dict.strokeWidthCount, true, true, true, false);
|
|
|
|
PutString(h, "currentdict end" XCF_NEW_LINE);
|
|
}
|
|
|
|
|
|
static void GetSubr(XCF_Handle h,
|
|
CardX index,
|
|
boolean unprocessed,
|
|
Card8 PTR_PREFIX * PTR_PREFIX *ppSubr,
|
|
Card16 PTR_PREFIX *pSubrLength)
|
|
{
|
|
Offset subrOffset, nextSubrOffset;
|
|
if (unprocessed)
|
|
{
|
|
XCF_LookUpTableEntry(h, &h->dict.localSubrs, index);
|
|
*pSubrLength = (Card16) h->inBuffer.blockLength;
|
|
*ppSubr = h->inBuffer.start;
|
|
}
|
|
else
|
|
{
|
|
subrOffset = *da_INDEX(h->type1.subrOffsets, index);
|
|
nextSubrOffset = *da_INDEX(h->type1.subrOffsets, index+1);
|
|
*pSubrLength = (Card16)(nextSubrOffset - subrOffset);
|
|
*ppSubr = da_INDEX(h->type1.subrs, subrOffset);
|
|
}
|
|
}
|
|
|
|
|
|
void XT1_CIDWriteSubrs(XCF_Handle h, Card16 fdIndex)
|
|
{
|
|
CardX i;
|
|
Card8 PTR_PREFIX *pSubr;
|
|
Card16 subrLength;
|
|
Card32 numberOfSubrs;
|
|
|
|
h->dict.localSubrs = h->type1.cid.localSubrs[fdIndex];
|
|
h->dict.localSubrBias = h->type1.cid.localSubrBias[fdIndex];
|
|
numberOfSubrs = h->options.outputCharstrType == 2 ?
|
|
h->dict.localSubrs.count : h->type1.subrOffsets.cnt - 1;
|
|
|
|
for (i=0 ; i < numberOfSubrs ; ++i)
|
|
{
|
|
GetSubr(h, i, h->options.outputCharstrType == 2, &pSubr, &subrLength);
|
|
PutType1CharString(h, pSubr, subrLength);
|
|
}
|
|
}
|
|
|
|
void XT1_CIDWriteSubrMap(XCF_Handle h, Card16 fdIndex)
|
|
{
|
|
CardX i;
|
|
Offset subrOffset = 0;
|
|
Card16 lenIVextraBytes = (h->options.lenIV == -1) ? 0 : h->options.lenIV;
|
|
Card32 accum = h->type1.cid.subrDataStart - h->type1.cid.charMapStart;
|
|
boolean unprocessed = h->options.outputCharstrType == 2;
|
|
Card32 numberOfSubrs = unprocessed ?
|
|
h->type1.cid.localSubrs[fdIndex].count : h->type1.subrOffsets.cnt;
|
|
|
|
for (i=0 ; i < numberOfSubrs ; ++i)
|
|
{
|
|
subrOffset = unprocessed ? i : *da_INDEX(h->type1.subrOffsets, i);
|
|
PutSizedNumber(h, accum + subrOffset, 4); /* xxx will change if SDBytes is not 4! */
|
|
accum += lenIVextraBytes;
|
|
}
|
|
}
|
|
|
|
static void GetCIDCharString(XCF_Handle h, Card8 PTR_PREFIX *PTR_PREFIX
|
|
*ppCharStr, Card16 PTR_PREFIX *charStrLength)
|
|
{
|
|
if ((h->options.outputCharstrType != 2) && (h->dict.fontType != 1))
|
|
{
|
|
*ppCharStr = h->type1.charStrs.array;
|
|
*charStrLength = (Card16) h->type1.charStrs.cnt;
|
|
}
|
|
else
|
|
{
|
|
XCF_LookUpTableEntry(h, &h->fontSet.charStrings, (Card16)h->type1.charStrs.cnt);
|
|
*charStrLength = (Card16) h->inBuffer.blockLength;
|
|
*ppCharStr = h->inBuffer.start;
|
|
}
|
|
}
|
|
|
|
void XT1_CIDWriteCharString(XCF_Handle h)
|
|
{
|
|
Card8 PTR_PREFIX *pCharStr;
|
|
Card16 charStrLength;
|
|
|
|
GetCIDCharString(h, &pCharStr, &charStrLength);
|
|
|
|
h->type1.cid.charDataCount += PutType1CharString(h, pCharStr, charStrLength);
|
|
*da_NEXT(h->type1.charStrOffsets) = h->type1.cid.charDataCount;
|
|
}
|
|
|
|
static void WriteDVSubr(XCF_Handle h, Card32 subrNum, StringID sid, Card16 lenIVextraBytes)
|
|
{
|
|
char PTR_PREFIX *pSubr;
|
|
Card16 length;
|
|
char str[50];
|
|
|
|
XCF_LookUpString(h, sid, &pSubr, &length);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "dup %ld %lu -| ", (long int)subrNum,
|
|
(long unsigned int) (length + lenIVextraBytes));
|
|
PutString(h, str);
|
|
PutType1CharString(h, (Card8 PTR_PREFIX *)pSubr, length);
|
|
PutString(h," |" XCF_NEW_LINE);
|
|
}
|
|
|
|
static void WriteSubrs(XCF_Handle h, boolean unprocessed)
|
|
{
|
|
CardX i;
|
|
char str[50];
|
|
Card8 PTR_PREFIX *pSubr;
|
|
Card16 subrLength;
|
|
Card16 lenIVextraBytes;
|
|
Card32 numberOfSubrs;
|
|
if (unprocessed)
|
|
numberOfSubrs = h->dict.localSubrs.count;
|
|
else
|
|
numberOfSubrs = h->type1.subrOffsets.cnt - 1;
|
|
|
|
if ((numberOfSubrs == 0) && !(h->dict.numberOfMasters && unprocessed))
|
|
return;
|
|
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "/Subrs %u array" XCF_NEW_LINE,
|
|
/* Add 2 for NDV, CDV */
|
|
numberOfSubrs + ((unprocessed && (h->dict.numberOfMasters > 0)) ? 2 : 0));
|
|
PutString(h,str);
|
|
lenIVextraBytes = (h->options.lenIV == -1) ? 0 : h->options.lenIV;
|
|
for (i=0;i<numberOfSubrs;++i)
|
|
{
|
|
GetSubr(h, i, unprocessed, &pSubr, &subrLength);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "dup %ld %lu -| ",(long int)i,(long unsigned int) (subrLength+lenIVextraBytes));
|
|
PutString(h, str);
|
|
PutType1CharString(h, pSubr, subrLength);
|
|
PutString(h," |" XCF_NEW_LINE);
|
|
}
|
|
if (unprocessed && (h->dict.numberOfMasters > 0))
|
|
{
|
|
WriteDVSubr(h, numberOfSubrs, h->dict.ndv, lenIVextraBytes);
|
|
WriteDVSubr(h, numberOfSubrs + 1, h->dict.cdv, lenIVextraBytes);
|
|
}
|
|
PutString(h,"|-" XCF_NEW_LINE);
|
|
}
|
|
|
|
static void GetCharstring(XCF_Handle h,
|
|
CardX index,
|
|
boolean unprocessed,
|
|
Card8 PTR_PREFIX * PTR_PREFIX *ppCharStr,
|
|
Card16 PTR_PREFIX *pCharStrLength)
|
|
{
|
|
Offset charStrOffset, nextCharStrOffset;
|
|
|
|
if (h->options.subrFlatten && !unprocessed)
|
|
/* Need to process the charstring first since we always re-use data
|
|
space in the DA charstring */
|
|
ProcessOneCharString(h, index);
|
|
else
|
|
/* We already processed all the charstrings, but we still need to
|
|
check for seac characters. */
|
|
CheckSeacCharString(h, index);
|
|
|
|
if (unprocessed)
|
|
{
|
|
XCF_LookUpTableEntry(h, &h->fontSet.charStrings, index);
|
|
*pCharStrLength = (Card16) h->inBuffer.blockLength;
|
|
*ppCharStr = h->inBuffer.start;
|
|
}
|
|
else
|
|
{
|
|
charStrOffset = *da_INDEX(h->type1.charStrOffsets,
|
|
h->options.subrFlatten ? 0 : index);
|
|
if (!h->options.subrFlatten)
|
|
{
|
|
nextCharStrOffset = *da_INDEX(h->type1.charStrOffsets, index+1);
|
|
*pCharStrLength = (Card16)(nextCharStrOffset - charStrOffset);
|
|
}
|
|
else
|
|
*pCharStrLength = (Card16)h->type1.charStrs.cnt;
|
|
*ppCharStr = da_INDEX(h->type1.charStrs, charStrOffset);
|
|
}
|
|
}
|
|
|
|
static Card32 GetSeacGlyphID(XCF_Handle h, CardX index)
|
|
{
|
|
char PTR_PREFIX *stdName;
|
|
char PTR_PREFIX *str;
|
|
Card16 len;
|
|
Card32 i;
|
|
Card32 id = (Card32)-1;
|
|
|
|
/* Get the correct glyph id for a seac character. Seac character index
|
|
always uses standard encoding
|
|
*/
|
|
if (h->dict.charset == cff_ISOAdobeCharset)
|
|
{
|
|
id = GetStdEncodeSID(index);
|
|
}
|
|
else if (index)
|
|
{
|
|
stdName = GetStdEncodingName(index);
|
|
|
|
if (index < h->fontSet.charStrings.count)
|
|
{ /* See if the glyph name matches the one in Standard encoding */
|
|
XCF_LookUpString(h, h->type1.pCharset[index-1], &str, &len);
|
|
if (len)
|
|
{
|
|
if (!h->callbacks.strcmp(stdName, str))
|
|
id = h->type1.pCharset[index - 1];
|
|
}
|
|
}
|
|
|
|
if (id == (Card32)-1)
|
|
{
|
|
/* Search for the glyphID. Worse case is we have to search the
|
|
entire charset. We may want to sort the character list to
|
|
improve the searching performance. */
|
|
|
|
|
|
for (i = 0; i < h->type1.charsetSize; i++)
|
|
{
|
|
XCF_LookUpString(h, h->type1.pCharset[i], &str, &len);
|
|
if (len)
|
|
{
|
|
if (!h->callbacks.strcmp(stdName, str))
|
|
{
|
|
id = i+1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
static unsigned short GetSeacCharacters(XCF_Handle h,
|
|
XCFGlyphID PTR_PREFIX *seacID)
|
|
{
|
|
Card32 gid;
|
|
unsigned short cSeacGlyphs;
|
|
|
|
cSeacGlyphs = 0;
|
|
if (h->cstr.baseSeac != 0)
|
|
{
|
|
gid = GetSeacGlyphID(h, h->cstr.baseSeac);
|
|
if (gid != -1)
|
|
seacID[cSeacGlyphs++] = (unsigned short)gid;
|
|
}
|
|
|
|
if (h->cstr.accentSeac != 0)
|
|
{
|
|
gid = GetSeacGlyphID(h, h->cstr.accentSeac);
|
|
if (gid != -1)
|
|
seacID[cSeacGlyphs++] = (unsigned short)gid;
|
|
}
|
|
|
|
return cSeacGlyphs;
|
|
}
|
|
|
|
static void WriteCharstringDict(XCF_Handle h)
|
|
{
|
|
char str[50];
|
|
Card32 numberOfCharString;
|
|
|
|
numberOfCharString = h->fontSet.charStrings.count;
|
|
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "2 index /CharStrings %lu dict dup begin" XCF_NEW_LINE, (long unsigned int) numberOfCharString);
|
|
PutString(h, str);
|
|
}
|
|
|
|
static void WriteCharstrings(XCF_Handle h, boolean flSeac,
|
|
short cGlyphs, XCFGlyphID PTR_PREFIX *pGlyphID,
|
|
unsigned char PTR_PREFIX **pGlyphName,
|
|
unsigned long PTR_PREFIX *pCharStrLength)
|
|
{
|
|
IntX i;
|
|
char str[50];
|
|
Card8 PTR_PREFIX *pCharStr;
|
|
Card16 charStrLength;
|
|
boolean flDownload;
|
|
boolean unprocessed;
|
|
boolean flCompleteFont = 0;
|
|
short glyphID;
|
|
Card16 lenIVextraBytes;
|
|
short totalGlyphs = cGlyphs;
|
|
|
|
unprocessed = (h->options.outputCharstrType == 2);
|
|
|
|
if (pCharStrLength && !flSeac)
|
|
*pCharStrLength = 0;
|
|
|
|
if (cGlyphs == -1)
|
|
/* Check to see if the request is to download the entire font */
|
|
{
|
|
totalGlyphs = (short)h->fontSet.charStrings.count;
|
|
flCompleteFont = 1;
|
|
}
|
|
|
|
lenIVextraBytes = (h->options.lenIV == -1) ? 0 : h->options.lenIV;
|
|
for (i=0; i < totalGlyphs; i++)
|
|
{
|
|
glyphID = (short)((flCompleteFont) ? i : *pGlyphID);
|
|
|
|
if (glyphID > (long)h->fontSet.charStrings.count)
|
|
XCF_FATAL_ERROR(h, XCF_InvalidGID, "bad Glyph ID", glyphID);
|
|
|
|
if (!flSeac)
|
|
flDownload = (!IS_GLYPH_SENT(h->dl.glyphs, glyphID));
|
|
else
|
|
{
|
|
flDownload = (h->options.dlOptions.useSpecialEncoding) ?
|
|
(!IS_GLYPH_SENT(h->dl.seacs, glyphID)) :
|
|
(!IS_GLYPH_SENT(h->dl.glyphs, glyphID));
|
|
}
|
|
|
|
if (flDownload)
|
|
{
|
|
PutString(h,"/");
|
|
PutCharacterName(h, pGlyphName ? i : glyphID, pGlyphName);
|
|
GetCharstring(h, glyphID, unprocessed, &pCharStr, &charStrLength);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " %lu -| ", (long unsigned int)
|
|
(charStrLength+lenIVextraBytes));
|
|
|
|
PutString(h,str);
|
|
PutType1CharString(h, pCharStr, charStrLength);
|
|
PutString(h," |-" XCF_NEW_LINE);
|
|
|
|
/* Set downloaded status for this glyph */
|
|
if (!flSeac)
|
|
SET_GLYPH_SENT_STATUS(h->dl.glyphs, glyphID);
|
|
else
|
|
{
|
|
if (h->options.dlOptions.useSpecialEncoding)
|
|
SET_GLYPH_SENT_STATUS(h->dl.seacs, glyphID);
|
|
else
|
|
SET_GLYPH_SENT_STATUS(h->dl.glyphs, glyphID);
|
|
}
|
|
|
|
if (pCharStrLength)
|
|
*pCharStrLength += (unsigned long)charStrLength;
|
|
|
|
/* Take care of seac characters .*/
|
|
if (!flCompleteFont && !flSeac)
|
|
{
|
|
XCFGlyphID seacID[2];
|
|
unsigned short cSeacGlyphs;
|
|
|
|
cSeacGlyphs = GetSeacCharacters(h, (XCFGlyphID *)seacID);
|
|
if (cSeacGlyphs)
|
|
{
|
|
/* Don't pass in the client's glyphName because:
|
|
1. We are downloading a seac's base or accent character.
|
|
2. The client uses a special encoding array that is not
|
|
derived from Adobe Standard Encoding (G00..GFF).
|
|
We need to use the real PS character name in this case.
|
|
*/
|
|
WriteCharstrings(h, 1, cSeacGlyphs, seacID, 0, pCharStrLength);
|
|
}
|
|
}
|
|
}
|
|
if (!flCompleteFont)
|
|
pGlyphID++;
|
|
}
|
|
} /* end WriteCharstrings */
|
|
|
|
/*
|
|
xxx complete
|
|
|
|
The following table shows the value types associated with various dict keys:
|
|
|
|
Key Type
|
|
--- ----
|
|
WeightVector Array
|
|
isFixedPitch Blend
|
|
* ItalicAngle Blend
|
|
* UnderlinePosition Blend
|
|
* UnderlineThickness Blend
|
|
StrokeWidth Blend
|
|
BlendDesignMap Array
|
|
BlendAxisTypes Array (of SIDs)
|
|
XUID Array
|
|
BaseFontBlend DeltaArray
|
|
* BlueValues BlendArray
|
|
* OtherBlues BlendArray
|
|
* FamilyBlues BlendArray
|
|
* FamilyOtherBlues BlendArray
|
|
* BlueScale Blend
|
|
* BlueShift Blend
|
|
* BlueFuzz Blend
|
|
* StdHW Blend
|
|
* StdVW Blend
|
|
* StemSnapH BlendArray
|
|
* StemSnapV BlendArray
|
|
|
|
*/
|
|
|
|
static void WritePrivateDict(XCF_Handle h, short cGlyphs,
|
|
XCFGlyphID PTR_PREFIX *pGlyphID,
|
|
unsigned char PTR_PREFIX **pGlyphName,
|
|
unsigned long PTR_PREFIX *pCharStrLength)
|
|
{
|
|
char line[MAX_LINE_LENGTH];
|
|
boolean unprocessed = (h->options.outputCharstrType == 2);
|
|
static XCFGlyphID notdefID = 0;
|
|
|
|
/**** Start Private Dict ****/
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "dup /Private %ld dict dup begin" XCF_NEW_LINE, (Card32) PrivateDictCount(h));
|
|
PutString(h,line);
|
|
if (h->options.hexEncoding && !h->options.eexecEncryption)
|
|
PutString(h, "/-|{string currentfile exch readhexstring pop}executeonly def" XCF_NEW_LINE);
|
|
else
|
|
PutString(h, "/-|{string currentfile exch readstring pop}executeonly def" XCF_NEW_LINE);
|
|
PutString(h, "/|-{" T1_NOACCESS "def}executeonly def" XCF_NEW_LINE);
|
|
PutString(h, "/|{" T1_NOACCESS "put}executeonly def" XCF_NEW_LINE);
|
|
|
|
/**** Write Private Dict ****/
|
|
|
|
if (!StreamKeyPointData(h, XCF_UID))
|
|
/* Duplicated from Font Dict */
|
|
WriteLongNumberLine(h, "UniqueID", h->dict.uniqueID, h->dict.uniqueIDCount);
|
|
if (!h->dict.blueValuesCount) /* Write BlueValues array if not present in cff */
|
|
PutString(h, "/BlueValues [ ] |-" XCF_NEW_LINE);
|
|
WriteBlendArrayLine(h, "BlueValues", h->dict.blueValues,
|
|
h->dict.blueValuesCount, true, true, true, false);
|
|
WriteBlendArrayLine(h, "OtherBlues", h->dict.otherBlues,
|
|
h->dict.otherBluesCount, true, true, true, false);
|
|
WriteBlendArrayLine(h, "FamilyBlues", h->dict.familyBlues,
|
|
h->dict.familyBluesCount, true, true, true, false);
|
|
WriteBlendArrayLine(h, "FamilyOtherBlues", h->dict.familyOtherBlues,
|
|
h->dict.familyOtherBluesCount, true, true, true, false);
|
|
|
|
WriteStemSnap(h, true);
|
|
WriteBlendLine(h, "BlueScale", h->dict.blueScale, h->dict.blueScaleCount,
|
|
true, true, true, true);
|
|
WriteBlendLine(h, "BlueShift", h->dict.blueShift, h->dict.blueShiftCount,
|
|
true, true, true, false);
|
|
WriteBlendLine(h, "BlueFuzz", h->dict.blueFuzz, h->dict.blueFuzzCount, true,
|
|
true, true, false);
|
|
WriteBlendBooleanLine(h, "ForceBold", h->dict.forceBold, h->dict.forceBoldCount, true, h->dict.forceBoldThreshold);
|
|
WriteNumberLine(h, "ForceBoldThreshold", h->dict.forceBoldThreshold,
|
|
h->dict.forceBoldThresholdCount, false);
|
|
if ((h->dict.languageGroupCount) && (h->dict.languageGroup == 1))
|
|
PutString(h, "/RndStemUp false def" XCF_NEW_LINE);
|
|
WriteLongNumberLine(h, "LanguageGroup", h->dict.languageGroup,
|
|
h->dict.languageGroupCount);
|
|
WriteNumberLine(h, "ExpansionFactor", h->dict.expansionFactor,
|
|
h->dict.expansionFactorCount, true);
|
|
WriteNumberLine(h, "initialRandomSeed", h->dict.initialRandomSeed,
|
|
h->dict.initialRandomSeedCount, false);
|
|
if (unprocessed)
|
|
{
|
|
WriteNumberLine(h, "defaultWidthX", h->dict.defaultWidthX,
|
|
h->dict.defaultWidthXCount, false);
|
|
WriteNumberLine(h, "nominalWidthX", h->dict.nominalWidthX,
|
|
h->dict.nominalWidthXCount, false);
|
|
/* Need to account for the NDV and CDV subrs in mmfonts. */
|
|
if (h->dict.localSubrs.count > 0)
|
|
WriteLongNumberLine(h, "subroutineNumberBias", h->dict.numberOfMasters ?
|
|
XCF_CalculateSubrBias(h->dict.localSubrs.count + 2) : h->dict.localSubrBias, 1);
|
|
}
|
|
if (h->dict.fontType == 2)
|
|
WriteLongNumberLine(h, "lenIV", h->options.lenIV, 1);
|
|
else if ((h->dict.fontType == 1) && (h->options.outputCharstrType == 1))
|
|
WriteLongNumberLine(h, "lenIV", h->dict.lenIV, h->dict.lenIVCount);
|
|
|
|
if (h->dict.numberOfMasters > 0)
|
|
{ /* Write out ndv, cdv and include as subroutines. */
|
|
Card32 subrNum = unprocessed ? h->dict.localSubrs.count:
|
|
h->type1.subrOffsets.cnt;
|
|
WriteLongNumberLine(h, "NDV", subrNum, 1);
|
|
WriteLongNumberLine(h, "CDV", subrNum + 1, 1);
|
|
if (h->options.outputCharstrType == 1)
|
|
XC_DVToSubr(h);
|
|
}
|
|
|
|
WriteLongNumberLine(h, "lenBuildCharArray", h->dict.lenBuildCharArray,
|
|
h->dict.lenBuildCharArrayCount);
|
|
if (h->dict.lenBuildCharArrayCount)
|
|
PutString(h, "/BuildCharArray lenBuildCharArray array def" XCF_NEW_LINE);
|
|
PutString(h, "/MinFeature {16 16} def" XCF_NEW_LINE);
|
|
PutString(h, "/password 5839 def" XCF_NEW_LINE);
|
|
WriteErode(h, true);
|
|
WritePrivateBlendDict(h);
|
|
|
|
if (h->dict.embeddedPostscriptCount)
|
|
{
|
|
PutStringID(h, (StringID)h->dict.embeddedPostscript);
|
|
PutString(h, XCF_NEW_LINE);
|
|
}
|
|
|
|
WriteOtherSubrs(h, h->cstr.flexUsed, (h->type1.subrOffsets.cnt > 5));
|
|
WriteSubrs(h, (h->options.outputCharstrType == 2));
|
|
WriteCharstringDict(h);
|
|
|
|
if (cGlyphs != -1)
|
|
/* Always download the .notdef character. */
|
|
WriteCharstrings(h, 0, 1, ¬defID, 0, pCharStrLength);
|
|
|
|
WriteCharstrings(h, 0, cGlyphs, pGlyphID, pGlyphName, pCharStrLength);
|
|
|
|
/* Flag -- Add support for
|
|
|
|
NDV
|
|
CDV
|
|
*/
|
|
}
|
|
|
|
static void T1Init(XCF_Handle h)
|
|
{
|
|
h->outBuffer.eexecOn = false;
|
|
}
|
|
|
|
/* Called for each dict in the FDArray of a CIDFont. */
|
|
void XT1_WriteCIDDict(XCF_Handle h, Card16 fd, Card32 subrMapOffset, Card16 subrCount)
|
|
{
|
|
char line[MAX_LINE_LENGTH];
|
|
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "dup %d" XCF_NEW_LINE, fd);
|
|
PutLine(h,line);
|
|
|
|
PutLine(h,"%ADOBeginFontDict");
|
|
h->callbacks.xcfSprintf(line, CCHOF(line),
|
|
"%ld dict" XCF_NEW_LINE "begin",
|
|
(Card32)FontDictCount(h) /* xxx wrong number? */);
|
|
PutLine(h,line);
|
|
|
|
if (h->dict.fdFontNameCount)
|
|
{
|
|
PutString(h, "/FontName /");
|
|
PutStringID(h, (StringID)h->dict.fdFontName);
|
|
PutLine(h, " def");
|
|
}
|
|
WriteLongNumberLine(h, "FontType", h->options.outputCharstrType, 1);
|
|
WriteFontMatrix(h, "FontMatrix", h->dict.fontMatrix, h->dict.fontMatrixCount);
|
|
WriteNumberLine(h, "PaintType", h->dict.paintType, h->dict.paintTypeCount, false);
|
|
|
|
PutLine(h,XCF_NEW_LINE "%ADOBeginPrivateDict");
|
|
h->callbacks.xcfSprintf(line, CCHOF(line),
|
|
"/Private %ld dict dup" XCF_NEW_LINE "begin",
|
|
(Card32)PrivateDictCount(h) /* xxx wrong number? */);
|
|
PutLine(h,line);
|
|
|
|
PutLine(h, "/MinFeature {16 16} def");
|
|
/* xxx deal with lenIV output */
|
|
if ((h->dict.fontType == 2) && (h->options.outputCharstrType == 1))
|
|
WriteLongNumberLine(h, "lenIV", h->options.lenIV, 1);
|
|
else if ((h->dict.fontType == 2) && (h->options.outputCharstrType == 2))
|
|
WriteLongNumberLine(h, "lenIV", -1, 1);
|
|
else if ((h->dict.fontType == 1) && (h->options.outputCharstrType == 1))
|
|
WriteLongNumberLine(h, "lenIV", h->dict.lenIV, h->dict.lenIVCount);
|
|
#ifdef T13
|
|
else
|
|
XT13_WritePrivDictValues(h);
|
|
#endif
|
|
WriteLongNumberLine(h, "LanguageGroup", h->dict.languageGroup,
|
|
h->dict.languageGroupCount);
|
|
if ((h->dict.languageGroupCount) && (h->dict.languageGroup == 1))
|
|
PutString(h, "/RndStemUp false def" XCF_NEW_LINE);
|
|
if ((h->dict.fontType == 2) && (h->options.outputCharstrType == 2))
|
|
{
|
|
WriteNumberLine(h, "defaultWidthX", h->dict.defaultWidthX,
|
|
h->dict.defaultWidthXCount, false);
|
|
WriteNumberLine(h, "nominalWidthX", h->dict.nominalWidthX,
|
|
h->dict.nominalWidthXCount, false);
|
|
}
|
|
if (!h->dict.blueValuesCount) /* Write BlueValues array if not present in cff */
|
|
PutString(h, "/BlueValues [ ] def" XCF_NEW_LINE);
|
|
WriteBlendArrayLine(h, "BlueValues", h->dict.blueValues,
|
|
h->dict.blueValuesCount, true, true, true, false);
|
|
WriteBlendArrayLine(h, "OtherBlues", h->dict.otherBlues,
|
|
h->dict.otherBluesCount, true, true, true, false);
|
|
WriteBlendLine(h, "BlueScale", h->dict.blueScale, h->dict.blueScaleCount,
|
|
true, true, true, true);
|
|
WriteBlendLine(h, "BlueShift", h->dict.blueShift, h->dict.blueShiftCount,
|
|
true, true, true, false);
|
|
WriteBlendLine(h, "BlueFuzz", h->dict.blueFuzz, h->dict.blueFuzzCount, true,
|
|
true, true, false);
|
|
WriteStemSnap(h, true);
|
|
WriteCIDOtherSubrs(h);
|
|
WriteErode(h, true);
|
|
PutLine(h, XCF_NEW_LINE "/password 5839 def" XCF_NEW_LINE);
|
|
if (subrCount)
|
|
{
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "/SubrMapOffset %d def", subrMapOffset);
|
|
PutLine(h,line);
|
|
PutLine(h, "/SDBytes 4 def");
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "/SubrCount %d def", subrCount);
|
|
PutLine(h,line);
|
|
}
|
|
|
|
PutLine(h, "end def" XCF_NEW_LINE
|
|
"%ADOEndPrivateDict" XCF_NEW_LINE XCF_NEW_LINE
|
|
"currentdict" XCF_NEW_LINE
|
|
"end" XCF_NEW_LINE
|
|
"%ADOEndFontDict" XCF_NEW_LINE XCF_NEW_LINE
|
|
"put");
|
|
}
|
|
|
|
/* Write top-level dict, up to FDArray */
|
|
#define MAX_FONTNAME_LENGTH 128
|
|
void XT1_WriteCIDTop(XCF_Handle h)
|
|
{
|
|
char line[MAX_LINE_LENGTH];
|
|
char fontName[MAX_FONTNAME_LENGTH];
|
|
|
|
T1Init(h);
|
|
|
|
PutLine(h, "%!PS-Adobe-3.0 Resource-CIDFont");
|
|
PutLine(h, "%%DocumentNeededResources: ProcSet (CIDInit)");
|
|
PutLine(h, "%%IncludeResource: ProcSet (CIDInit)");
|
|
|
|
/* FontName */
|
|
if (!h->options.dlOptions.fontName)
|
|
{
|
|
Card16 length = sizeof(fontName) - 1;
|
|
XCF_LookUpTableEntry(h, &h->fontSet.fontNames, h->fontSet.fontIndex);
|
|
if ((Card16)h->inBuffer.blockLength < length)
|
|
length = (Card16)h->inBuffer.blockLength;
|
|
h->callbacks.memcpy(fontName, (Card8 PTR_PREFIX *)h->inBuffer.start, length);
|
|
fontName[length] = '\0';
|
|
}
|
|
else
|
|
{
|
|
Card16 length = h->callbacks.strlen((char PTR_PREFIX *)h->options.dlOptions.fontName);
|
|
if (length > (sizeof(fontName) - 1))
|
|
length = sizeof(fontName) - 1;
|
|
h->callbacks.memcpy(fontName, h->options.dlOptions.fontName, length);
|
|
fontName[length] = '\0';
|
|
}
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "%%%%BeginResource: CIDFont (%s)", fontName);
|
|
PutLine(h,line);
|
|
|
|
/* Title */
|
|
PutString(h, "%%Title: (");
|
|
PutStringID(h, (StringID) h->dict.fullName);
|
|
PutString(h, " ");
|
|
PutStringID(h, (StringID) h->dict.ROS[0]);
|
|
PutString(h, " ");
|
|
PutStringID(h, (StringID) h->dict.ROS[1]);
|
|
PutString(h, " ");
|
|
PutLongNumber(h, h->dict.ROS[2]);
|
|
PutLine(h, ")");
|
|
|
|
/* Version */
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "%%%%Version: %s", h->dict.cidFontVersion);
|
|
PutLine(h,line);
|
|
|
|
PutLine(h, XCF_NEW_LINE "/CIDInit /ProcSet findresource begin" XCF_NEW_LINE);
|
|
|
|
PutLine(h, "20 dict begin" XCF_NEW_LINE);
|
|
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "/CIDFontName /%s def", fontName);
|
|
PutLine(h,line);
|
|
if (h->dict.cidFontVersionCount > 0)
|
|
{
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "/CIDFontVersion %s def", h->dict.cidFontVersion);
|
|
PutLine(h,line);
|
|
}
|
|
WriteLongNumberLine(h, "CIDFontType", h->dict.cidFontType,
|
|
h->dict.cidFontTypeCount);
|
|
|
|
PutLine(h, XCF_NEW_LINE "/CIDSystemInfo 3 dict dup begin");
|
|
WriteSIDLine(h, "Registry", h->dict.ROS[0], h->dict.ROSCount);
|
|
WriteSIDLine(h, "Ordering", h->dict.ROS[1], h->dict.ROSCount);
|
|
WriteLongNumberLine(h, "Supplement", h->dict.ROS[2], h->dict.ROSCount);
|
|
PutLine(h, "end def" XCF_NEW_LINE);
|
|
|
|
WriteNumberListLine(h, "FontBBox", h->dict.fontBBox, h->dict.fontBBoxCount, false);
|
|
PutString(h, XCF_NEW_LINE);
|
|
|
|
// JJIA: fix bug 366539. Added Metrics2 for vertical printing.
|
|
PutLine(h, "/Metrics2 16 dict def" XCF_NEW_LINE);
|
|
PutLine(h, "/CDevProc {pop 4 index add} bind def" XCF_NEW_LINE);
|
|
|
|
if ( h->options.uniqueIDMethod != XCF_UNDEFINE_UID )
|
|
{
|
|
WriteLongNumberLine(h, "UIDBase", h->dict.uidBase, h->dict.uidBaseCount);
|
|
WriteLongNumberListLine(h, "XUID", h->dict.xUID, h->dict.xUIDCount);
|
|
}
|
|
|
|
PutLine(h, XCF_NEW_LINE "/FontInfo 3 dict dup begin");
|
|
WriteSIDLine(h, "Notice", h->dict.notice, h->dict.noticeCount);
|
|
WriteSIDLine(h, "FullName", h->dict.fullName, h->dict.fullNameCount);
|
|
if (h->callbacks.getFSType)
|
|
{
|
|
long fsType;
|
|
|
|
h->callbacks.getFSType(h, &fsType, h->callbacks.getFSTypeHook);
|
|
if (fsType != -1)
|
|
WriteLongNumberLine(h, "FSType", fsType, 1);
|
|
}
|
|
|
|
// GOODNAME
|
|
if (h->callbacks.isKnownROS)
|
|
{
|
|
long knownROS;
|
|
char PTR_PREFIX *R;
|
|
Card16 lenR;
|
|
char PTR_PREFIX *O;
|
|
Card16 lenO;
|
|
|
|
XCF_LookUpString(h, (StringID) h->dict.ROS[0], &R, &lenR);
|
|
XCF_LookUpString(h, (StringID) h->dict.ROS[1], &O, &lenO);
|
|
h->callbacks.isKnownROS(h, &knownROS,
|
|
R, lenR,
|
|
O, lenO,
|
|
h->dict.ROS[2],
|
|
h->callbacks.isKnownROSHook);
|
|
if (knownROS == 0)
|
|
{
|
|
PutLine(h, "/GlyphNames2Unicode 16 dict def");
|
|
PutLine(h, "/GlyphNames2HostCode 16 dict def");
|
|
}
|
|
}
|
|
|
|
PutLine(h,
|
|
"end" T1_READONLY " def" XCF_NEW_LINE XCF_NEW_LINE
|
|
"/CIDMapOffset 0 def" XCF_NEW_LINE XCF_NEW_LINE
|
|
"/GDBytes 4 def");
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "/FDBytes %s def", (h->type1.cid.fdCount > 1 ? "1" : "0"));
|
|
PutLine(h,line);
|
|
|
|
#ifdef T13
|
|
XT13_WriteSetup(h);
|
|
#endif
|
|
|
|
WriteLongNumberLine(h, "CIDCount", h->dict.cidCount, h->dict.cidCountCount);
|
|
h->type1.cid.cidCount = (Card32) h->dict.cidCount;
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), XCF_NEW_LINE "/FDArray %d array", h->type1.cid.fdCount);
|
|
PutLine(h,line);
|
|
}
|
|
|
|
static Card16 CalculateTotalSubrLength(XCF_Handle h, boolean unprocessed)
|
|
{
|
|
Card16 subrLength = 0;
|
|
Card8 PTR_PREFIX *pSubr;
|
|
Card16 len;
|
|
Card16 fd;
|
|
Card16 lenIVextraBytes;
|
|
CardX i;
|
|
Card32 numberOfSubrs;
|
|
|
|
lenIVextraBytes = (h->options.lenIV == -1) ? 0 : h->options.lenIV;
|
|
for (fd = 0; fd < h->type1.cid.fdCount; fd++)
|
|
{
|
|
h->dict.localSubrs = h->type1.cid.localSubrs[fd];
|
|
h->dict.localSubrBias = h->type1.cid.localSubrBias[fd];
|
|
numberOfSubrs = unprocessed ? h->dict.localSubrs.count :
|
|
h->type1.subrOffsets.cnt - 1;
|
|
subrLength += (Card16)(lenIVextraBytes * numberOfSubrs);
|
|
for (i = 0; i < numberOfSubrs; ++i)
|
|
{
|
|
GetSubr(h, i, unprocessed, &pSubr, &len);
|
|
subrLength += len;
|
|
}
|
|
}
|
|
return subrLength;
|
|
}
|
|
|
|
/* Totals the number of local subrs in each font dictionary. */
|
|
static Card16 TotalLocalSubrCount(XCF_Handle h)
|
|
{
|
|
Card16 fd;
|
|
Card16 total = 0;
|
|
|
|
if (CIDFONT)
|
|
{
|
|
for (fd = 0; fd < h->type1.cid.fdCount; fd++)
|
|
total += (Card16)h->type1.cid.localSubrs[fd].count;
|
|
}
|
|
else
|
|
total = (Card16)h->dict.localSubrs.count;
|
|
|
|
return total;
|
|
}
|
|
|
|
/* Write the binary section for a VM resident CIDFont. In this case
|
|
the binary section only contains the SubrMap and subr data.
|
|
For now only the standard subrs are written out. */
|
|
void XT1_WriteCIDVMBinarySection(XCF_Handle h)
|
|
{
|
|
boolean unprocessed = (h->options.outputCharstrType == 2);
|
|
Card16 subrLength = CalculateTotalSubrLength(h, unprocessed);
|
|
Card16 subrMapLength;
|
|
Card16 fd;
|
|
Card32 totalLen;
|
|
char str[MAX_LINE_LENGTH];
|
|
|
|
/* The SubrMap length is the SDBytes value which currently is always 4. */
|
|
subrMapLength = (Card16)(unprocessed ? TotalLocalSubrCount(h) * 4 : ((h->type1.subrOffsets.cnt * 4) * h->type1.cid.fdCount));
|
|
totalLen = subrLength + subrMapLength;
|
|
|
|
PutString(h, "%%BeginData: ");
|
|
if (h->options.hexEncoding)
|
|
{
|
|
/* totalLen * 2 - double the data size because it's hex
|
|
25 - to account for (Hex) ... StartData
|
|
2 - for the > to end hex data and newline
|
|
*/
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "%8ld Binary Bytes%s", (Card32)(totalLen * 2) + 25 + ((subrLength > 0) ? 2 : 0), XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "(Hex) %8ld StartData%s", (Card32)totalLen, XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
}
|
|
else /* binary */
|
|
{
|
|
/* The extra 28 bytes is to account for (Binary) ... StartData */
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "%8ld Binary Bytes", (Card32)totalLen + 28);
|
|
PutString(h, str);
|
|
PutString(h, XCF_NEW_LINE);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "(Binary) %8ld StartData ", (Card32)totalLen);
|
|
PutString(h, str);
|
|
}
|
|
if (subrLength != 0)
|
|
{
|
|
h->type1.cid.flags |= WRITE_SUBR_FLAG;
|
|
for (fd = 0; fd < h->type1.cid.fdCount; ++fd)
|
|
XT1_CIDWriteSubrMap(h, fd);
|
|
for (fd = 0; fd < h->type1.cid.fdCount; ++fd)
|
|
XT1_CIDWriteSubrs(h, fd);
|
|
h->type1.cid.flags &= 0xFFFD; /* Reset WriteSubr flag */
|
|
}
|
|
if (h->options.hexEncoding && (subrLength > 0))
|
|
PutString(h, ">" XCF_NEW_LINE); /* indicate end of hex data */
|
|
PutString(h, "%%EndData" XCF_NEW_LINE "%%EndResource" XCF_NEW_LINE);
|
|
}
|
|
|
|
void XT1_CIDBeginBinarySection(XCF_Handle h)
|
|
{
|
|
Card16 i;
|
|
|
|
PutString(h, "%%BeginData: ");
|
|
h->type1.cid.replaceSD1 = XCF_OutputPos(h);
|
|
PutLine(h, "12345678 Binary Bytes");
|
|
if (h->options.hexEncoding)
|
|
PutString(h, "(Hex) ");
|
|
else
|
|
PutString(h, "(Binary) ");
|
|
h->type1.cid.replaceSD2 = XCF_OutputPos(h);
|
|
PutString(h, "12345678 StartData ");
|
|
h->type1.cid.charMapStart = XCF_OutputPos(h);
|
|
|
|
/* put placeholders for the charmap */
|
|
/* The +1 is for the final interval */
|
|
for (i = 0 ; i < h->type1.cid.cidCount + 1 ; ++i)
|
|
{
|
|
if (h->type1.cid.cidCount > 1)
|
|
XT1_PutT1Data(h, (Card8 *)"chars", 5); /* If GD or FDBytes changes this
|
|
can change. */
|
|
else
|
|
XT1_PutT1Data(h, (Card8 *)"char", 4);
|
|
}
|
|
h->type1.cid.subrMapStart = XCF_OutputPos(h);
|
|
/* before this was missing the offset of the start of the binary data */
|
|
h->type1.cid.subrDataStart += h->type1.cid.charMapStart;
|
|
}
|
|
|
|
void XT1_CIDEndBinarySection(XCF_Handle h)
|
|
{
|
|
char line[MAX_LINE_LENGTH];
|
|
Card32 charOffset = h->type1.cid.charDataStart - h->type1.cid.charMapStart;
|
|
XCF_SetOuputPosition(h, h->type1.cid.replaceSD1);
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "%8ld",
|
|
charOffset + h->type1.cid.charDataCount + h->type1.cid.replaceSD2 - h->type1.cid.replaceSD1);
|
|
PutString(h, line);
|
|
XCF_SetOuputPosition(h, h->type1.cid.replaceSD2);
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "%8ld", charOffset + h->type1.cid.charDataCount);
|
|
PutString(h, line);
|
|
XCF_SetOuputPosition(h, h->type1.cid.charDataEnd);
|
|
if (h->options.hexEncoding)
|
|
PutString(h, ">" XCF_NEW_LINE);
|
|
PutString(h, "%%EndData" XCF_NEW_LINE "%%EndResource" XCF_NEW_LINE);
|
|
}
|
|
|
|
void XT1_CIDWriteCharMap(XCF_Handle h)
|
|
{
|
|
Card16 i;
|
|
Card32 charOffset = h->type1.cid.charDataStart - h->type1.cid.charMapStart;
|
|
CardX interval;
|
|
StringID *charset = h->type1.pCharset;
|
|
char fdBytes = (h->type1.cid.fdCount > 1 ? 1 : 0);
|
|
|
|
XCF_SetOuputPosition(h, h->type1.cid.charMapStart);
|
|
|
|
/* Output the notdef character, which is always required. */
|
|
if (fdBytes)
|
|
PutSizedNumber(h, XCF_GetFDIndex(h, 0), 1); /* xxx will change if FDBytes changes! */
|
|
PutSizedNumber(h, charOffset, 4); /* xxx will change if GDBytes changes! */
|
|
|
|
/* Write out any empty intervals between 0 and charset[0]. */
|
|
for (i = 1; i < charset[0]; i++)
|
|
{
|
|
if (fdBytes)
|
|
PutSizedNumber(h, 255, 1);
|
|
PutSizedNumber(h, charOffset + h->type1.charStrOffsets.array[0], 4);
|
|
}
|
|
|
|
/* The charset array does not include the notdef character, but the
|
|
FDIndex array does include the notdef character. */
|
|
for (i = 0; i < h->type1.charsetSize; i++)
|
|
{
|
|
if (fdBytes)
|
|
PutSizedNumber(h, XCF_GetFDIndex(h, i+1), 1);
|
|
PutSizedNumber(h, charOffset + h->type1.charStrOffsets.array[i], 4);
|
|
if (i + 1 < h->type1.charsetSize)
|
|
for (interval = charset[i] + 1; interval < charset[i+1]; interval++)
|
|
{ /* Write empty interval */
|
|
if (fdBytes)
|
|
PutSizedNumber(h, 255, 1);
|
|
PutSizedNumber(h, charOffset + h->type1.charStrOffsets.array[i+1], 4);
|
|
}
|
|
}
|
|
/* Put ending location, and fill out to end of table. */
|
|
for (interval = charset[i-1]; interval < h->type1.cid.cidCount; interval++)
|
|
{
|
|
if (fdBytes)
|
|
PutSizedNumber(h, 255, 1);
|
|
PutSizedNumber(h, charOffset + h->type1.charStrOffsets.array[i], 4);
|
|
}
|
|
}
|
|
|
|
/* Write the prolog for a CIDFont in VM when the initial font is created. */
|
|
static void WriteCIDBaseFontProlog(XCF_Handle h)
|
|
{
|
|
#if HAS_COOLTYPE_UFL == 1
|
|
/* In CoolType the GlyphDirectory procedures are stored in a dictionary,
|
|
ct_GlyphDirProcs, that is downloaded once by the client in a procset.
|
|
*/
|
|
PutString(h, "ct_GlyphDirProcs begin" XCF_NEW_LINE);
|
|
#endif
|
|
PutString(h, "GlyphDirectory" XCF_NEW_LINE);
|
|
#if HAS_COOLTYPE_UFL == 1
|
|
PutString(h, "+" XCF_NEW_LINE);
|
|
#else
|
|
PutString(h, "5 dict begin/$ exch def/? $ type/dicttype eq def/|{?{def}{$ 3 1 roll put}" XCF_NEW_LINE);
|
|
PutString(h, "ifelse}bind def/!{?{end}if end}bind def/:{string currentfile exch readstring" XCF_NEW_LINE);
|
|
PutString(h, "pop}executeonly def ?{$ begin}if" XCF_NEW_LINE);
|
|
#endif
|
|
}
|
|
|
|
/* Write the prolog for a CIDFont in VM when incrementally adding glyphs. */
|
|
static void WriteGlyphDictProlog(XCF_Handle h, short cGlyphs)
|
|
{
|
|
char str[MAX_LINE_LENGTH];
|
|
|
|
#if HAS_COOLTYPE_UFL == 1
|
|
/* Put these dicts on the stack so the correct findresource call is made and
|
|
the GlyphDirectory procedures are defined. */
|
|
PutString(h, "ct_Dict begin ct_MakeOCF begin ct_GlyphDirProcs begin" XCF_NEW_LINE);
|
|
#endif
|
|
|
|
PutString(h, "/");
|
|
PutFontName(h);
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), " %ld%s", (long int)cGlyphs, XCF_NEW_LINE);
|
|
PutString(h, str);
|
|
#if HAS_COOLTYPE_UFL == 1
|
|
PutString(h, "GetGlyphDirectory" XCF_NEW_LINE);
|
|
#else
|
|
PutString(h, "systemdict/languagelevel known not{1 index/CIDFont findresource/GlyphDirectory" XCF_NEW_LINE);
|
|
PutString(h, "get dup type/dicttype eq{dup dup maxlength exch length sub 2 index lt{dup" XCF_NEW_LINE);
|
|
PutString(h, "length 2 index add dict copy 2 index/CIDFont findresource/GlyphDirectory 2" XCF_NEW_LINE);
|
|
PutString(h, "index put}if}if exch pop exch pop}{pop/CIDFont findresource/GlyphDirectory get" XCF_NEW_LINE);
|
|
PutString(h, "}ifelse 5 dict begin/$ exch def/? $ type/dicttype eq def/|{?{def}{$ 3 1 roll" XCF_NEW_LINE);
|
|
PutString(h, "put}ifelse}bind def/!{?{end}if end}bind def/:{string currentfile exch" XCF_NEW_LINE);
|
|
PutString(h, "readstring pop}executeonly def ?{$ begin}if" XCF_NEW_LINE);
|
|
#endif
|
|
}
|
|
|
|
static void WriteOneGlyphDictEntry(XCF_Handle h, XCFGlyphID glyphID, unsigned
|
|
long PTR_PREFIX *pCharStrLength)
|
|
{
|
|
char line[MAX_LINE_LENGTH];
|
|
Card8 fd = 0;
|
|
Card16 charStrLength = 0;
|
|
Card8 PTR_PREFIX *pCharStr;
|
|
Card16 fdIndexLen = (h->type1.cid.fdCount > 1) ? 1 : 0;
|
|
Card16 id;
|
|
Card16 lenIVextraBytes = (h->options.lenIV == -1) ? 0 : h->options.lenIV;
|
|
|
|
if (h->callbacks.getCharStr == 0)
|
|
{
|
|
if (h->options.outputCharstrType != 2)
|
|
ProcessOneCharString(h, (unsigned int)glyphID);
|
|
else
|
|
/* So GetCIDCharString gets the string from the charstr table. */
|
|
h->type1.charStrs.cnt = glyphID;
|
|
|
|
GetCIDCharString(h, &pCharStr, &charStrLength);
|
|
|
|
id = glyphID ? h->type1.pCharset[glyphID-1] : 0;
|
|
|
|
}
|
|
else
|
|
{
|
|
h->callbacks.getCharStr((XFhandle)h, glyphID, &pCharStr, &charStrLength,
|
|
&fd, h->callbacks.getCharStrHook);
|
|
id = (Card16) glyphID; /* In this case glyphID == cid. */
|
|
}
|
|
|
|
if (h->options.hexEncoding)
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "%d <", id);
|
|
else
|
|
/* If FDBytes is variable then the amt to add to charStrLength changes. */
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "%d %d : ", id, (charStrLength + fdIndexLen + lenIVextraBytes));
|
|
XCF_PutData(h, (Card8 PTR_PREFIX *)line, h->callbacks.strlen(line));
|
|
/* If there is more than one value in the FDArray then the first
|
|
byte in the charstring must be the FD index. */
|
|
if (h->type1.cid.fdCount > 1)
|
|
{
|
|
/* According to the spec the index byte must not be encrypted. */
|
|
if (h->callbacks.getCharStr == 0)
|
|
fd = XCF_GetFDIndex(h, glyphID);
|
|
if (h->options.hexEncoding)
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "%02X", (int)fd);
|
|
else
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "%c", fd);
|
|
XCF_PutData(h, (Card8 PTR_PREFIX *)line, h->callbacks.strlen(line));
|
|
}
|
|
PutType1CharString(h, pCharStr, charStrLength);
|
|
if (h->options.hexEncoding)
|
|
PutString(h, ">");
|
|
PutString(h, " |" XCF_NEW_LINE);
|
|
SET_GLYPH_SENT_STATUS(h->dl.glyphs, glyphID);
|
|
if (pCharStrLength)
|
|
*pCharStrLength += (unsigned long)charStrLength;
|
|
}
|
|
|
|
/* Creates the GlyphDirectory dictionary for VM resident CIDFonts.
|
|
Hex and binary encoding is supported. The client is responsible
|
|
for knowing whether the download channel supports binary data. */
|
|
void XT1_WriteGlyphDictEntries(XCF_Handle h, short cGlyphs,
|
|
XCFGlyphID PTR_PREFIX *pGlyphID,
|
|
unsigned long PTR_PREFIX *pCharStrLength)
|
|
{
|
|
IntX i;
|
|
char line[MAX_LINE_LENGTH];
|
|
short totalGlyphs;
|
|
long glyphID;
|
|
boolean dlEntireFont = cGlyphs == -1 ? 1 : 0;
|
|
|
|
if (pCharStrLength)
|
|
*pCharStrLength = 0;
|
|
|
|
totalGlyphs = dlEntireFont ? h->fontSet.charStrings.count : cGlyphs;
|
|
|
|
if (h->dl.state == XCF_DL_INIT)
|
|
{
|
|
/* Add one to the total to make sure the .notdef character is included. */
|
|
h->callbacks.xcfSprintf(line, CCHOF(line), "/GlyphDirectory %d dict def", dlEntireFont ?
|
|
totalGlyphs : totalGlyphs + 1);
|
|
PutLine(h, line);
|
|
WriteCIDBaseFontProlog(h);
|
|
/* Ensure the .notdef character is included. */
|
|
if (!dlEntireFont)
|
|
WriteOneGlyphDictEntry(h, 0, pCharStrLength);
|
|
}
|
|
for (i = 0; i < totalGlyphs; i++)
|
|
{
|
|
glyphID = dlEntireFont ? i : *pGlyphID;
|
|
if (glyphID > (long)h->fontSet.charStrings.count)
|
|
XCF_FATAL_ERROR(h, XCF_InvalidGID, "bad Glyph ID", glyphID);
|
|
if (!IS_GLYPH_SENT(h->dl.glyphs, glyphID))
|
|
WriteOneGlyphDictEntry(h, glyphID, pCharStrLength);
|
|
if (!dlEntireFont)
|
|
pGlyphID++;
|
|
}
|
|
PutString(h, "!" XCF_NEW_LINE); /* ! is the name of the cleanup proc. */
|
|
|
|
#if HAS_COOLTYPE_UFL == 1
|
|
if (h->dl.state != XCF_DL_INIT)
|
|
PutString(h, "end end end" XCF_NEW_LINE); /* end for ct_Dict, ct_MakeOCF, ct_GlyphDirProcs */
|
|
else
|
|
PutString(h, "end" XCF_NEW_LINE); /* end for ct_GlyphDirProcs */
|
|
#endif
|
|
}
|
|
|
|
void XT1_WriteAdditionalGlyphDictEntries(XCF_Handle h,
|
|
short cGlyphs, XCFGlyphID PTR_PREFIX *pGlyphID,
|
|
unsigned long PTR_PREFIX *pCharStrLength)
|
|
{
|
|
WriteGlyphDictProlog(h, cGlyphs);
|
|
XT1_WriteGlyphDictEntries(h, cGlyphs, pGlyphID, pCharStrLength);
|
|
}
|
|
|
|
void XT1_WriteT1Font(XCF_Handle h)
|
|
{
|
|
IntX i;
|
|
|
|
T1Init(h);
|
|
WriteFontDict(h);
|
|
if (h->options.eexecEncryption)
|
|
StartEexec(h);
|
|
WritePrivateDict(h, -1, 0, 0, 0);
|
|
PutString(h, "end" XCF_NEW_LINE "end" XCF_NEW_LINE T1_READONLY "put" XCF_NEW_LINE T1_NOACCESS "put" XCF_NEW_LINE "dup/FontName get exch definefont pop" XCF_NEW_LINE);
|
|
if (h->options.eexecEncryption)
|
|
{
|
|
PutString(h, "mark currentfile closefile\n"); /* must be terminated with line feed (\n) only */
|
|
StopEexec(h);
|
|
PutString(h, XCF_NEW_LINE);
|
|
for (i=1;i<=8;++i)
|
|
PutString(h, "0000000000000000000000000000000000000000000000000000000000000000" XCF_NEW_LINE);
|
|
PutString(h,"cleartomark" XCF_NEW_LINE);
|
|
}
|
|
}
|
|
|
|
void XT1_WriteFontSubset(XCF_Handle h, short cGlyphs,
|
|
XCFGlyphID PTR_PREFIX *pGlyphID,
|
|
unsigned char PTR_PREFIX **pGlyphName,
|
|
unsigned long PTR_PREFIX *pCharStrLength)
|
|
{
|
|
IntX i;
|
|
|
|
T1Init(h);
|
|
|
|
WriteFontDict(h);
|
|
if (h->options.eexecEncryption)
|
|
StartEexec(h);
|
|
else
|
|
PutString(h, "systemdict begin" XCF_NEW_LINE);
|
|
WritePrivateDict(h, cGlyphs, pGlyphID, pGlyphName, pCharStrLength);
|
|
PutString(h, "end" XCF_NEW_LINE "end" XCF_NEW_LINE T1_READONLY "put" XCF_NEW_LINE T1_NOACCESS "put" XCF_NEW_LINE "dup/FontName get exch definefont pop" XCF_NEW_LINE);
|
|
if (h->options.eexecEncryption)
|
|
{
|
|
PutString(h, "mark currentfile closefile\n"); /* must be terminated with line feed only */
|
|
StopEexec(h);
|
|
PutString(h, XCF_NEW_LINE);
|
|
for (i=1;i<=8;++i)
|
|
PutString(h, "0000000000000000000000000000000000000000000000000000000000000000" XCF_NEW_LINE);
|
|
PutString(h,"cleartomark" XCF_NEW_LINE);
|
|
}
|
|
else
|
|
PutString(h, "end" XCF_NEW_LINE); /* "end" for systemdict begin */
|
|
}
|
|
|
|
static void WriteAdditionalProlog(XCF_Handle h)
|
|
{
|
|
if (h->options.eexecEncryption)
|
|
StopEexec(h);
|
|
PutString(h, "" XCF_NEW_LINE);
|
|
PutString(h, "" XCF_NEW_LINE);
|
|
if (h->options.eexecEncryption)
|
|
StartEexec(h);
|
|
else /* eexec makes the systemdict current. When encryption is off this
|
|
must be done explicitly. */
|
|
PutString(h, "systemdict begin" XCF_NEW_LINE);
|
|
PutString(h, "/");
|
|
PutFontName(h);
|
|
PutString(h, " findfont dup" XCF_NEW_LINE);
|
|
PutString(h, "/Private get dup rcheck" XCF_NEW_LINE);
|
|
PutString(h, "{begin true}{pop false}ifelse exch" XCF_NEW_LINE);
|
|
PutString(h, "/CharStrings get begin" XCF_NEW_LINE);
|
|
}
|
|
|
|
static void WriteAdditionalEpilog(XCF_Handle h)
|
|
{
|
|
int i;
|
|
|
|
PutString(h, "end {end}if" XCF_NEW_LINE); /* end of the charstrings */
|
|
if (h->options.eexecEncryption)
|
|
{
|
|
PutString(h, "mark currentfile closefile\n"); /* must be terminated with
|
|
line feed only */
|
|
StopEexec(h);
|
|
PutString(h, ""XCF_NEW_LINE);
|
|
for(i = 0;i < 8;i++)
|
|
PutString(h, "0000000000000000000000000000000000000000000000000000000000000000" XCF_NEW_LINE);
|
|
PutString(h, "cleartomark" XCF_NEW_LINE);
|
|
}
|
|
else
|
|
PutString(h, "end" XCF_NEW_LINE); /* "end" for systemdict begin */
|
|
}
|
|
|
|
void XT1_WriteAdditionalFontSubset(XCF_Handle h,
|
|
short cGlyphs, XCFGlyphID PTR_PREFIX *pGlyphID,
|
|
unsigned char PTR_PREFIX **pGlyphName,
|
|
unsigned long PTR_PREFIX *pCharStrLength)
|
|
{
|
|
WriteAdditionalProlog(h);
|
|
WriteCharstrings(h, 0, cGlyphs, pGlyphID, pGlyphName, pCharStrLength);
|
|
WriteAdditionalEpilog(h);
|
|
}
|
|
|
|
void XT1_ShowHexString(XCF_Handle h,
|
|
unsigned char PTR_PREFIX *hexString,
|
|
boolean showCtrlD)
|
|
{
|
|
short i, j;
|
|
char str[50];
|
|
boolean done = false;
|
|
|
|
PutString(h, "/inch {72 mul} def" XCF_NEW_LINE);
|
|
PutString(h, "/");
|
|
PutFontName(h);
|
|
PutString(h, " findfont" XCF_NEW_LINE);
|
|
PutString(h, "0.5 inch scalefont" XCF_NEW_LINE);
|
|
PutString(h, "setfont" XCF_NEW_LINE);
|
|
for ( i = 0; !done; i++)
|
|
{
|
|
h->callbacks.xcfSprintf(str, CCHOF(str), "%s0.5 inch %d inch moveto%s", XCF_NEW_LINE,
|
|
10 - i, XCF_NEW_LINE );
|
|
PutString(h, str);
|
|
PutString(h, "<");
|
|
for (j = 0; j <= 40;)
|
|
{
|
|
str[j++] = *hexString++;
|
|
str[j++] = *hexString++;
|
|
if (*hexString == '\0')
|
|
{
|
|
done = true;
|
|
break;
|
|
}
|
|
}
|
|
str[j] = '\0';
|
|
PutString(h, str);
|
|
PutString(h, "> show " XCF_NEW_LINE);
|
|
if (i > 9)
|
|
{
|
|
i = -1;
|
|
PutString(h, "showpage" XCF_NEW_LINE);
|
|
}
|
|
}
|
|
PutString(h, "showpage" XCF_NEW_LINE);
|
|
|
|
if (showCtrlD)
|
|
PutString(h, "\004");
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|