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.
477 lines
11 KiB
477 lines
11 KiB
/*
|
|
* Adobe Universal Font Library
|
|
*
|
|
* Copyright (c) 1996 Adobe Systems Inc.
|
|
* All Rights Reserved
|
|
*
|
|
* UFLStrm.c
|
|
*
|
|
* UTL Output Stream Implementation
|
|
*
|
|
*
|
|
* $Header:
|
|
*/
|
|
|
|
/* -------------------------------------------------------------------------
|
|
Header Includes
|
|
--------------------------------------------------------------------------- */
|
|
#include "UFLCnfig.h"
|
|
#include "UFLPriv.h"
|
|
#include "UFLMem.h"
|
|
#include "UFLErr.h"
|
|
#include "UFLStrm.h"
|
|
#include "UFLStd.h"
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Constants
|
|
--------------------------------------------------------------------------- */
|
|
#define kEOLSpacing 60
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Global Variables
|
|
--------------------------------------------------------------------------- */
|
|
static char fHexBytes[16] = { '0', '1', '2', '3',
|
|
'4', '5', '6', '7',
|
|
'8', '9', 'a', 'b',
|
|
'c', 'd', 'e', 'f' };
|
|
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Implementation
|
|
--------------------------------------------------------------------------- */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
Function UFLOutStream
|
|
|
|
Constructor of the object.
|
|
|
|
--------------------------------------------------------------------------- */
|
|
|
|
|
|
UFLHANDLE
|
|
StrmInit(
|
|
const UFLMemObj *pMem,
|
|
const UFLStream *stream,
|
|
const UFLBool outputAscii
|
|
)
|
|
{
|
|
UFLOutStream *pOut;
|
|
|
|
pOut = (UFLOutStream *)UFLNewPtr( pMem, sizeof(UFLOutStream) );
|
|
if ( pOut )
|
|
{
|
|
pOut->pMem = pMem;
|
|
pOut->pStream = stream;
|
|
pOut->flOutputAscii = outputAscii;
|
|
pOut->lAddEOL = 0;
|
|
}
|
|
|
|
return (UFLHANDLE)pOut;
|
|
}
|
|
|
|
void
|
|
StrmCleanUp(
|
|
UFLHANDLE h
|
|
)
|
|
{
|
|
UFLDeletePtr( ((UFLOutStream *)h)->pMem, h );
|
|
}
|
|
|
|
UFLErrCode
|
|
StrmPutBytes (
|
|
const UFLHANDLE h,
|
|
const char *data,
|
|
const UFLsize_t len,
|
|
const UFLBool bAscii
|
|
)
|
|
{
|
|
UFLsize_t cb = len;
|
|
long selector;
|
|
UFLOutStream *pOut = (UFLOutStream *)h;
|
|
|
|
/* If we can output binary data then simply send out the data */
|
|
if ( StrmCanOutputBinary(h) )
|
|
selector = kUFLStreamPut;
|
|
else /* otherwise, if the data is binary, request the stream to convert the data to the transport protocol */
|
|
selector = ( bAscii ) ? kUFLStreamPut : kUFLStreamPutBinary;
|
|
|
|
pOut->pStream->put( (UFLStream*)pOut->pStream, selector, (void*)data, &cb );
|
|
if ( cb != (unsigned int)len )
|
|
return kErrOutput;
|
|
else return kNoErr;
|
|
}
|
|
|
|
UFLErrCode
|
|
StrmPutAsciiHex(
|
|
const UFLHANDLE h,
|
|
const char *data,
|
|
const unsigned long len
|
|
)
|
|
{
|
|
unsigned long byteCount = 0;
|
|
unsigned char *c = (unsigned char*)data, tmp, put[2];
|
|
UFLErrCode retVal = kNoErr;
|
|
UFLOutStream *pOut = (UFLOutStream *)h;
|
|
char nullStr[] = "\0\0"; // An empty/Null string.
|
|
|
|
while ( byteCount < len )
|
|
{
|
|
tmp = *c++;
|
|
put[0] = fHexBytes[(tmp >> 4) & 0x0f];
|
|
put[1] = fHexBytes[tmp & 0x0f];
|
|
|
|
if ( (retVal = StrmPutBytes( h, (const char*)put, 2, 1 ) ) != kNoErr )
|
|
{
|
|
break;
|
|
}
|
|
|
|
pOut->lAddEOL += 2;
|
|
if ( pOut->lAddEOL == kEOLSpacing )
|
|
{
|
|
if ( (retVal = StrmPutStringEOL( h, nullStr )) != kNoErr )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
++byteCount;
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
|
|
UFLErrCode
|
|
StrmPutWordAsciiHex(
|
|
const UFLHANDLE h,
|
|
const unsigned short wData
|
|
)
|
|
{
|
|
unsigned char tmp, put[5];
|
|
UFLErrCode retVal;
|
|
UFLOutStream *pOut = (UFLOutStream *)h;
|
|
|
|
StrmPutString(h, "<");
|
|
|
|
tmp = (unsigned char) GET_HIBYTE(wData);
|
|
put[0] = fHexBytes[(tmp >> 4) & 0x0f];
|
|
put[1] = fHexBytes[tmp & 0x0f];
|
|
|
|
tmp = (unsigned char) GET_LOBYTE(wData);
|
|
put[2] = fHexBytes[(tmp >> 4) & 0x0f];
|
|
put[3] = fHexBytes[tmp & 0x0f];
|
|
|
|
retVal = StrmPutBytes( h, (const char*)put, 4, 1 ); //last 1 == use ASCII format
|
|
|
|
StrmPutString(h, ">");
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
UFLErrCode
|
|
StrmPutString(
|
|
const UFLHANDLE h,
|
|
const char *s
|
|
)
|
|
{
|
|
if ( s )
|
|
{
|
|
if ( *s )
|
|
return StrmPutBytes( h, s, UFLstrlen(s), 1 );
|
|
else
|
|
return kNoErr;
|
|
}
|
|
else return kErrInvalidParam;
|
|
}
|
|
|
|
UFLErrCode
|
|
StrmPutStringEOL(
|
|
const UFLHANDLE h,
|
|
const char *s
|
|
)
|
|
{
|
|
UFLErrCode retVal = kNoErr;
|
|
#ifdef WIN_ENV
|
|
static char c[2] = { kWinLineEnd, kLineEnd };
|
|
#else
|
|
static char c[1] = { kLineEnd };
|
|
#endif
|
|
|
|
if ( s == nil )
|
|
return kErrInvalidParam;
|
|
|
|
if ( *s )
|
|
retVal = StrmPutString( h, s );
|
|
|
|
if ( retVal == kNoErr ) {
|
|
((UFLOutStream *)h)->lAddEOL = 0; /* Initialize number of bytes in a line to 0 */
|
|
#ifdef WIN_ENV
|
|
retVal = StrmPutBytes( h, c, 2, 1 ); /* lfcr that the user sees */
|
|
#else
|
|
retVal = StrmPutBytes( h, c, 1, 1 );
|
|
#endif
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
UFLErrCode
|
|
StrmPutStringBinary(
|
|
const UFLHANDLE h,
|
|
const char *data,
|
|
const unsigned long len
|
|
)
|
|
{
|
|
char buf[128], c;
|
|
char *pSrc, *pDest;
|
|
short maxBuf, bufSize;
|
|
unsigned long count;
|
|
UFLErrCode retVal = kNoErr;
|
|
|
|
if ( data == nil || len == 0 )
|
|
return kNoErr;
|
|
|
|
pSrc = (char*) data;
|
|
maxBuf = sizeof( buf );
|
|
count = (unsigned long) len;
|
|
while ( count && retVal == kNoErr )
|
|
{
|
|
/* copy data to temp buffer */
|
|
for ( pDest = (char*)buf, bufSize = 0; count && bufSize < maxBuf -1; )
|
|
{
|
|
c = *pSrc++;
|
|
if ( ( c == '(' ) || ( c == ')' ) || ( c == '\\' ) ) { /* escape of those characters */
|
|
*pDest++ = '\\' ; /* by preceding '\' */
|
|
bufSize++;
|
|
}
|
|
*pDest++ = c; /* Add the byte itself */
|
|
bufSize++;
|
|
count--;
|
|
}
|
|
|
|
/* Send the escape data */
|
|
if ( bufSize )
|
|
retVal = StrmPutBytes( h, buf, bufSize, 0 );
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
UFLErrCode
|
|
StrmPutInt(
|
|
const UFLHANDLE h,
|
|
const long int i
|
|
)
|
|
{
|
|
char is[11]; /* One bigger than format */
|
|
|
|
UFLsprintf((char *)is, CCHOF(is), "%ld", i);
|
|
return StrmPutString( h, is );
|
|
}
|
|
|
|
static long convFract[] =
|
|
{
|
|
65536L,
|
|
6553L,
|
|
655L,
|
|
66L,
|
|
6L
|
|
};
|
|
|
|
/* Convert a Fixed to a c string */
|
|
static void Fixed2CString(
|
|
UFLFixed f,
|
|
char *s,
|
|
short precision,
|
|
char skipTrailSpace
|
|
)
|
|
{
|
|
char u[12];
|
|
char *t;
|
|
short v;
|
|
char sign;
|
|
long fracPrec = (precision <= 4) ? convFract[precision] : 0L;
|
|
|
|
if ((sign = f < 0) != 0)
|
|
f = -f;
|
|
|
|
/* If f started out as fixedMax or -fixedMax, the precision adjustment puts it
|
|
out of bounds. Reset it correctly. */
|
|
if (f >= 0x7FFF7FFF)
|
|
f =(UFLFixed)0x7fffffff;
|
|
else
|
|
f += (fracPrec + 1) >> 1;
|
|
|
|
v = (short)(f >> 16);
|
|
f &= 0x0000ffff;
|
|
if (sign && (v || f >= fracPrec))
|
|
*s++ = '-';
|
|
|
|
t = u;
|
|
do
|
|
{
|
|
*t++ = v % 10 + '0';
|
|
v /= 10;
|
|
} while (v);
|
|
|
|
for (; t > u;)
|
|
*s++ = *--t;
|
|
|
|
if (f >= fracPrec)
|
|
{
|
|
*s++ = '.';
|
|
for (v = precision; v-- && f;)
|
|
{
|
|
f = (f << 3) + (f << 1);
|
|
*s++ = (char)((f >> 16) + '0');
|
|
f &= 0x0000ffff;
|
|
}
|
|
for (; *--s == '0';)
|
|
;
|
|
if (*s != '.')
|
|
s++;
|
|
}
|
|
if ( !skipTrailSpace )
|
|
*s++ = ' ';
|
|
*s = '\0';
|
|
}
|
|
|
|
|
|
UFLErrCode
|
|
StrmPutFixed(
|
|
const UFLHANDLE h,
|
|
const UFLFixed fixed
|
|
)
|
|
{
|
|
char str[32];
|
|
|
|
Fixed2CString( fixed, str, 4, 0 );
|
|
return StrmPutString( h, str );
|
|
}
|
|
|
|
|
|
UFLErrCode
|
|
StrmPutMatrix(
|
|
const UFLHANDLE h,
|
|
const UFLFixedMatrix *matrix,
|
|
const UFLBool skipEF
|
|
)
|
|
{
|
|
UFLErrCode retVal;
|
|
|
|
retVal = StrmPutString( h, "[" );
|
|
if ( retVal == kNoErr )
|
|
retVal = StrmPutFixed( h, matrix->a );
|
|
if ( retVal == kNoErr )
|
|
retVal = StrmPutFixed( h, matrix->b );
|
|
if ( retVal == kNoErr )
|
|
retVal = StrmPutFixed( h, matrix->c );
|
|
if ( retVal == kNoErr )
|
|
retVal = StrmPutFixed( h, matrix->d );
|
|
|
|
if ( 0 == skipEF )
|
|
{
|
|
if ( retVal == kNoErr )
|
|
retVal = StrmPutFixed( h, matrix->e );
|
|
if ( retVal == kNoErr )
|
|
retVal = StrmPutFixed( h, matrix->f );
|
|
}
|
|
|
|
if ( retVal == kNoErr )
|
|
retVal = StrmPutString( h, "] " );
|
|
|
|
return retVal;
|
|
}
|
|
|
|
UFLErrCode
|
|
StrmPutAscii85(
|
|
const UFLHANDLE h,
|
|
const char *data,
|
|
const unsigned long len
|
|
)
|
|
{
|
|
char *cptr;
|
|
short bCount;
|
|
unsigned long val;
|
|
UFLErrCode retVal = kNoErr;
|
|
UFLOutStream *pOut = (UFLOutStream *)h;
|
|
unsigned long i;
|
|
|
|
/* encode the initial 4-tuples */
|
|
cptr = (char *)data;
|
|
val = 0UL;
|
|
bCount = 0;
|
|
pOut->lAddEOL = 0;
|
|
for ( i = 0; retVal == kNoErr && i < len; i++ )
|
|
{
|
|
val <<= 8;
|
|
val |= (unsigned char)*cptr++;
|
|
if ( bCount == 3 )
|
|
{
|
|
retVal = Output85( h, val, 5 );
|
|
val = 0UL;
|
|
bCount = 0;
|
|
}
|
|
else
|
|
{
|
|
bCount ++;
|
|
}
|
|
}
|
|
|
|
/* now do the last partial 4-tuple -- if there is one */
|
|
/* see the Red Book spec for the rules on how this is done */
|
|
if ( retVal == kNoErr && bCount > 0 )
|
|
{
|
|
short dex;
|
|
short rem = 4 - bCount; /* count the remaining bytes */
|
|
|
|
for ( dex = 0; dex < rem; dex ++ ) /* shift left for each of them */
|
|
val <<= 8; /* (equivalent to adding in ZERO's)*/
|
|
retVal = Output85( h, val, (short)(bCount + 1) ); /* output only meaningful bytes + 1 */
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
UFLErrCode
|
|
Output85(
|
|
const UFLHANDLE h,
|
|
unsigned long inWord,
|
|
short nBytes
|
|
)
|
|
{
|
|
UFLErrCode retVal = kNoErr;
|
|
unsigned char outChar;
|
|
UFLOutStream *pOut = (UFLOutStream *)h;
|
|
char nullStr[] = "\0\0"; // An empty/Null string.
|
|
|
|
if ( (inWord == 0UL) && (nBytes == 5) )
|
|
{
|
|
outChar = 'z';
|
|
StrmPutBytes( h, (const char*)&outChar, 1, 1 );
|
|
pOut->lAddEOL++;
|
|
}
|
|
else
|
|
{
|
|
unsigned long power;
|
|
short count;
|
|
|
|
power = 52200625UL; // 85 ^ 4
|
|
for ( count = 0; retVal == kNoErr && count < nBytes; count ++)
|
|
{
|
|
outChar = (unsigned char)( (unsigned long)(inWord / power) + (unsigned long)'!' );
|
|
retVal = StrmPutBytes( h, (const char*)&outChar, 1, 1 );
|
|
pOut->lAddEOL++;
|
|
if ( count < 4 )
|
|
{
|
|
inWord %= power;
|
|
power /= 85;
|
|
}
|
|
}
|
|
}
|
|
if ( pOut->lAddEOL >= kEOLSpacing )
|
|
{
|
|
retVal = StrmPutStringEOL( h, nullStr );
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|