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

2777 lines
76 KiB

/* @(#)CM_VerSion xcf_cstr.c atm09 1.2 16499.eco sum= 34614 atm09.002 */
/* @(#)CM_VerSion xcf_cstr.c atm08 1.6 16345.eco sum= 33712 atm08.005 */
/***********************************************************************/
/* */
/* Copyright 1990-1995 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. */
/* */
/***********************************************************************/
/* If Init fails you are done. If any other function fails you must call clean up */
#ifndef XCF_DUMP
#include "xcf_priv.h"
#else
#include <stdio.h>
#ifndef _SIZE_T
#define _SIZE_T /* so size_t isn't redefined here */
#include "xcf_priv.h"
#undef _SIZE_T
#else
#include "xcf_priv.h"
#endif
#endif
#ifdef T13
#include "xcf_t13.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct /* Individual charstring record */
{
unsigned short length;
char *cstr;
} Charstring;
typedef struct /* Transitional char record */
{
StringID sid;
Charstring cstr;
} TransChar;
static void FlattenSubr(XCF_Handle h, unsigned int depth, boolean PTR_PREFIX
*endcharFound, boolean localSubr);
static void WriteT1Data(XCF_Handle h, Card8 *pData, CardX length, boolean subr)
{
CardX i;
if (subr)
for (i=0;i<length;++i)
*da_NEXT(h->type1.subrs) = *pData++;
else
for (i=0;i<length;++i)
*da_NEXT(h->type1.charStrs) = *pData++;
}
void XC_WriteT1OpCode(XCF_Handle h, Card16 opCode, boolean subr)
{
Card8 output[2] = {tx_escape};
output[1] = (Card8) OpCode(opCode);
if (IsEscOp(opCode))
WriteT1Data(h, output, 2, subr);
else
WriteT1Data(h, output + 1, 1, subr);
}
static void NewT1CharStr(XCF_Handle h)
{
if (CIDFONT)
{
if ((h->options.outputCharstrType != 2) && (h->dict.fontType != 1))
h->type1.charStrs.cnt = 0;
}
else
{
*da_NEXT(h->type1.charStrOffsets) = h->type1.charStrs.cnt;
}
}
static void FreeT1CharStr(XCF_Handle h)
{
h->type1.charStrs.cnt = 0;
h->type1.charStrOffsets.cnt = 0;
*da_NEXT(h->type1.charStrOffsets) = 0;
}
#if 0
static void FreeT1Subr(XCF_Handle h)
{
h->type1.subrs.cnt = 0;
h->type1.subrOffsets.cnt = 0;
*da_NEXT(h->type1.subrOffsets) = 0;
}
#endif
static void NewT1Subr(XCF_Handle h)
{
if (h->type1.subrs.cnt)
XC_WriteT1OpCode(h, tx_return, true);
*da_NEXT(h->type1.subrOffsets) = h->type1.subrs.cnt;
}
/* Encode Int32 number and return length */
static Card16 IntToCharstr(Int32 i, Card8 PTR_PREFIX *t)
{
if (-107 <= i && i <= 107)
{
/* Single byte number */
t[0] = (Card8)(i + 139);
t[1] = '\0';
return 1;
}
else if (108 <= i && i <= 1131)
{
/* +ve 2-byte number */
i -= 108;
t[0] = (Card8)((i>>8) + 247);
t[1] = (Card8) i;
t[2] = '\0';
return 2;
}
else if (-1131 <= i && i <= -108)
{
/* -ve 2-byte number */
i += 108;
t[0] = (Card8)((-i>>8) + 251);
t[1] = (Card8) -i;
t[2] = '\0';
return 2;
}
else
{
/* 5-byte fixed point */
t[0] = 255;
t[1] = (Card8) (i>>24 & 0x0ff);
t[2] = (Card8) (i>>16 & 0x0ff);
t[3] = (Card8) (i>>8 & 0x0ff);
t[4] = (Card8) (i & 0x0ff);
t[5] = '\0';
return 5;
}
}
/*
Convert a fixed point number into a charstring of the form "int int div".
The second int in the charstring passed in is the "denominator".
*/
static Card16 ConvertFixedDiv(Fixed f, Card8 PTR_PREFIX *t, Int32 denominator)
{
Int32 numerator;
Card16 length;
boolean negative = false;
if (f < 0)
{
negative = true;
f = -f;
}
/*
Multiply by denominator and round to nearest integer.
Process upper and lower 16 bits seperately to avoid overflow.
*/
numerator = (f >> 16) * denominator;
numerator += (((f & 0x0000ffff) * denominator) + 0x08000) >> 16;
if (negative)
numerator = -numerator;
length = IntToCharstr(numerator, t);
length += IntToCharstr(denominator, t+length);
t[length] = (Card8) tx_escape;
t[length+1] = (Card8) OpCode(tx_div);
t[length+2] = '\0';
return length+2;
}
/*
Calculates how close to zero or one the fractional part of
a fixed point number is after it is multiplied by the integer
passed in "denominator".
*/
static Card32 CalculateTolerance(Fixed f, Card32 denominator)
{
Card32 tolerance;
if (f < 0) /* Force number to be positive */
f = -f;
/* multiply and truncate integer part (leaving fractional part) */
tolerance = (f * denominator) & 0x0000ffff;
if (tolerance > 0x08000) /* If greater than 0.5 then use 1 - tolerance */
tolerance = 0x10000 - tolerance;
return (tolerance);
}
#define DIV_MIN_TOLERANCE 64 /* 64/65536 = ~0.001 */
/* Encode 16.16 fixed point number and return length */
static Card16 FixedToCharstr(Fixed f, Card8 PTR_PREFIX *t)
{
Int32 denominator, bestDenominator;
Int32 tolerance, bestTolerance;
/* If integer then convert to "int" format and return */
if (!(f & 0x0000ffff))
return IntToCharstr(f>>16, t);
/* Otherwise it's a fraction so convert to "int int div" format */
/* Try common cases 10 and 100 first */
if (CalculateTolerance(f, 10) < DIV_MIN_TOLERANCE)
return (ConvertFixedDiv(f, t, 10));
else if (CalculateTolerance(f, 100) < DIV_MIN_TOLERANCE)
return (ConvertFixedDiv(f, t, 100));
/*
Try all cases between 2 and 199. This can be slow
but it should only run all the way through if no
close match is found. This will never happen for
known fonts. If it does happen then the closest
match between 2 and 199 will be used.
*/
bestDenominator = 1;
bestTolerance = 0x0ffff;
for (denominator=2; denominator < 200; ++denominator)
{
tolerance = CalculateTolerance(f, denominator);
if (tolerance < DIV_MIN_TOLERANCE)
return (ConvertFixedDiv(f, t, denominator));
else if (tolerance < bestTolerance)
{
bestTolerance = tolerance;
bestDenominator = denominator;
}
}
return (ConvertFixedDiv(f, t, bestDenominator));
}
static void WriteFixed(XCF_Handle h, Fixed f, boolean subr)
{
Card8 str[30];
Card16 length;
length = FixedToCharstr(f, str);
if (length == 0)
XCF_FATAL_ERROR(h, XCF_InvalidNumber, "FixedToCharstr failed.", 0 );
else
WriteT1Data(h, str, length, subr);
}
void XC_WriteT1PStackValue(XCF_Handle h, PStackValue psv, boolean subr)
{
IntX i;
Fixed initialValue = INT_TO_FIXED(0);
if (!psv->blend)
{
WriteFixed(h, psv->value[0], subr);
}
else
{
WriteFixed(h, psv->value[0], subr);
initialValue = psv->value[0];
for (i=1; i<h->dict.numberOfMasters; ++i)
{
WriteFixed(h, psv->value[i] - initialValue, subr);
}
WriteFixed(h, INT_TO_FIXED(6), subr);
XC_WriteT1OpCode(h, tx_callsubr, subr);
}
}
/* StackValue Manipulation Routines */
#define NEXTSTACKVALUE(p, offset, svSize) (PStackValue)(p+offset); \
offset += svSize;
static void NewStackValues(XCF_Handle h, void PTR_PREFIX * PTR_PREFIX *p,
Card32 cStackValues, Card16 PTR_PREFIX *svSize)
{
Card16 totalSize;
/* Allocate the data space for all the stack values that we need */
*svSize = SIZEOF_STACK_VALUES((h->dict.numberOfMasters) ? h->dict.numberOfMasters : 1);
totalSize = (Card16)(*svSize * cStackValues);
*p = 0;
if (!h->callbacks.allocate(p, totalSize, h->callbacks.allocateHook))
XCF_FATAL_ERROR(h, XCF_MemoryAllocationError, "StackValue Allocation Failure.", totalSize);
h->callbacks.memset((void PTR_PREFIX *)*p, 0, totalSize);
}
static PStackValue IntToPSV(void PTR_PREFIX *psv, Int32 i)
{
((PShortStackValue)psv)->blend = false;
((PShortStackValue)psv)->value = INT_TO_FIXED(i);
return (PStackValue)psv;
}
static void FixedToPSV(void PTR_PREFIX *psv, Fixed f)
{
((PShortStackValue)psv)->blend = false;
((PShortStackValue)psv)->value = f;
}
static void PSVFixedAdd(XCF_Handle h, PStackValue psv, Fixed f)
{
IntX i;
if (psv->blend)
for (i = 0; i < h->dict.numberOfMasters; ++i)
psv->value[i] += f;
else
psv->value[0] += f;
}
static void PSVCopy(XCF_Handle h, PStackValue pdest, PStackValue psrc)
{
IntX i;
if (pdest != psrc)
{
pdest->blend = psrc->blend;
if (psrc->blend)
for (i=0; i < h->dict.numberOfMasters; ++i)
pdest->value[i] = psrc->value[i];
else
pdest->value[0] = psrc->value[0];
}
}
static void PSVFixedSubtract(XCF_Handle h, PStackValue psv, Fixed f)
{
IntX i;
if (psv->blend)
for (i = 0; i < h->dict.numberOfMasters; ++i)
psv->value[i] -= f;
else
psv->value[0] -= f;
}
static void FixedPSVSubtract(XCF_Handle h, PStackValue psv, Fixed f)
{
IntX i;
if (psv->blend)
for (i = 0; i < h->dict.numberOfMasters; ++i)
psv->value[i] = f - psv->value[i];
else
psv->value[0] = f - psv->value[0];
}
static void PSVRealAdd(XCF_Handle h, PStackValue psv, Fixed d)
{
IntX i;
if (psv->blend)
for (i = 0; i < h->dict.numberOfMasters; ++i)
psv->value[i] += d;
else
psv->value[0] += d;
}
/* psvDest cannot equal psv1 or psv2! */
static void PStackValueAdd(XCF_Handle h, PStackValue psvDest, PStackValue psv1, PStackValue psv2)
{
IntX i;
if (!psv1->blend)
{
PSVCopy(h,psvDest, psv2);
PSVFixedAdd(h, psvDest, psv1->value[0]);
}
else if (!psv2->blend)
{
PSVCopy(h,psvDest, psv1);
PSVFixedAdd(h, psvDest, psv2->value[0]);
}
else
{
PSVCopy(h,psvDest, psv1);
for (i = 0; i < h->dict.numberOfMasters; ++i)
psvDest->value[i] += psv2->value[i];
}
}
#define PSVAdd(h, psvDest, psv1, psv2) ((!h->dict.numberOfMasters)?FixedToPSV(psvDest, (psv1)->value[0]+(psv2)->value[0]): PStackValueAdd(h, psvDest, psv1, psv2))
/* psvDest cannot equal psv1 or psv2! */
static void PSVSubtract(XCF_Handle h, PStackValue psvDest, PStackValue psv1, PStackValue psv2)
{
IntX i;
if (!psv1->blend)
{
PSVCopy(h,psvDest, psv2);
FixedPSVSubtract(h, psvDest, psv1->value[0]);
}
else if (!psv2->blend)
{
PSVCopy(h,psvDest, psv1);
PSVFixedSubtract(h, psvDest, psv2->value[0]);
}
else
{
PSVCopy(h,psvDest, psv1);
for (i = 0; i < h->dict.numberOfMasters; ++i)
psvDest->value[i] -= psv2->value[i];
}
}
static void PStackValueAdd4(XCF_Handle h, PStackValue psvDest, PStackValue psv1, PStackValue psv2, PStackValue psv3, PStackValue psv4)
{
StackValue temp1, temp2;
PStackValueAdd(h, &temp1, psv1, psv2);
PStackValueAdd(h, &temp2, &temp1, psv3);
PStackValueAdd(h, psvDest, &temp2, psv4);
}
#define PSVAdd4(h, psvDest, psv1, psv2, psv3, psv4) ((!h->dict.numberOfMasters)?FixedToPSV(psvDest, (psv1)->value[0]+(psv2)->value[0]+(psv3)->value[0]+(psv4)->value[0]): PStackValueAdd4(h, psvDest, psv1, psv2, psv3, psv4))
static void PSVAdd5(XCF_Handle h, PStackValue psvDest, PStackValue psv1, PStackValue psv2, PStackValue psv3, PStackValue psv4, PStackValue psv5)
{
StackValue temp;
PSVAdd4(h,&temp,psv1,psv2,psv3,psv4);
PStackValueAdd(h,psvDest,&temp,psv5);
}
static void PSVAdd7(XCF_Handle h, PStackValue psvDest, PStackValue psv1, PStackValue psv2, PStackValue psv3, PStackValue psv4, PStackValue psv5, PStackValue psv6, PStackValue psv7)
{
StackValue temp;
PSVAdd4(h,&temp,psv1,psv2,psv3,psv4);
PSVAdd4(h,psvDest,&temp,psv5,psv6,psv7);
}
/***************************************************/
/************************** Basic Operations ******************************/
static void Hsbw(XCF_Handle h, PStackValue psbx, PStackValue pwx, boolean subr)
{
XC_WriteT1PStackValue(h, psbx, subr);
XC_WriteT1PStackValue(h, pwx, subr);
XC_WriteT1OpCode(h, t1_hsbw, subr);
#ifdef XCF_DUMP
printf("%g %g <hsbw> ", FIXED_TO_REAL(psbx->value[0]), FIXED_TO_REAL(pwx->value[0]));
#endif
}
static void RMoveTo(XCF_Handle h, PStackValue pdx, PStackValue pdy, boolean subr)
{
StackValue temp;
if ((!pdx->blend) && (pdx->value[0] == 0))
{
XC_WriteT1PStackValue(h, pdy, subr);
XC_WriteT1OpCode(h, tx_vmoveto, subr);
}
else if ((!pdy->blend) && (pdy->value[0] == 0))
{
XC_WriteT1PStackValue(h, pdx, subr);
XC_WriteT1OpCode(h, tx_hmoveto, subr);
}
else
{
XC_WriteT1PStackValue(h, pdx, subr);
XC_WriteT1PStackValue(h, pdy, subr);
XC_WriteT1OpCode(h, tx_rmoveto, subr);
}
PSVCopy(h, &temp, h->cstr.x);
PSVAdd(h, h->cstr.x, &temp, pdx);
PSVCopy(h, &temp, h->cstr.y);
PSVAdd(h, h->cstr.y, &temp, pdy);
#ifdef XCF_DUMP
printf("%g %g <rmoveto> ", FIXED_TO_REAL(pdx->value[0]), FIXED_TO_REAL(pdy->value[0]));
#endif
}
static void RLineTo(XCF_Handle h, PStackValue pdx, PStackValue pdy, boolean subr)
{
StackValue temp;
if ((!pdx->blend) && (pdx->value[0] == 0))
{
XC_WriteT1PStackValue(h, pdy, subr);
XC_WriteT1OpCode(h, tx_vlineto, subr);
}
else if ((!pdy->blend) && (pdy->value[0] == 0))
{
XC_WriteT1PStackValue(h, pdx, subr);
XC_WriteT1OpCode(h, tx_hlineto, subr);
}
else
{
XC_WriteT1PStackValue(h, pdx, subr);
XC_WriteT1PStackValue(h, pdy, subr);
XC_WriteT1OpCode(h, tx_rlineto, subr);
}
PSVCopy(h, &temp, h->cstr.x);
PSVAdd(h, h->cstr.x, &temp, pdx);
PSVCopy(h, &temp, h->cstr.y);
PSVAdd(h, h->cstr.y, &temp, pdy);
#ifdef XCF_DUMP
printf("%g %g <rlineto> ", FIXED_TO_REAL(pdx->value[0]), FIXED_TO_REAL(pdy->value[0]));
#endif
}
static void RRCurveTo(XCF_Handle h, PStackValue pdx1, PStackValue pdy1,
PStackValue pdx2, PStackValue pdy2, PStackValue pdx3,
PStackValue pdy3, boolean subr)
{
StackValue temp;
if ( ((!pdy1->blend) && (pdy1->value[0] == 0)) && ((!pdx3->blend) && (pdx3->value[0] == 0)))
{
XC_WriteT1PStackValue(h, pdx1, subr);
XC_WriteT1PStackValue(h, pdx2, subr);
XC_WriteT1PStackValue(h, pdy2, subr);
XC_WriteT1PStackValue(h, pdy3, subr);
XC_WriteT1OpCode(h, tx_hvcurveto, subr);
}
else if ( ((!pdx1->blend) && (pdx1->value[0] == 0)) && ((!pdy3->blend) && (pdy3->value[0] == 0)))
{
XC_WriteT1PStackValue(h, pdy1, subr);
XC_WriteT1PStackValue(h, pdx2, subr);
XC_WriteT1PStackValue(h, pdy2, subr);
XC_WriteT1PStackValue(h, pdx3, subr);
XC_WriteT1OpCode(h, tx_vhcurveto, subr);
}
else
{
XC_WriteT1PStackValue(h, pdx1, subr);
XC_WriteT1PStackValue(h, pdy1, subr);
XC_WriteT1PStackValue(h, pdx2, subr);
XC_WriteT1PStackValue(h, pdy2, subr);
XC_WriteT1PStackValue(h, pdx3, subr);
XC_WriteT1PStackValue(h, pdy3, subr);
XC_WriteT1OpCode(h, tx_rrcurveto, subr);
}
PSVCopy(h, &temp, h->cstr.x);
PSVAdd4(h, h->cstr.x, &temp, pdx1, pdx2, pdx3);
PSVCopy(h, &temp, h->cstr.y);
PSVAdd4(h, h->cstr.y, &temp, pdy1, pdy2, pdy3);
#ifdef XCF_DUMP
printf("%g %g %g %g %g %g <rrcurveto> ", FIXED_TO_REAL(pdx1->value[0]), FIXED_TO_REAL(pdy1->value[0]), FIXED_TO_REAL(pdx2->value[0]), FIXED_TO_REAL(pdy2->value[0]), FIXED_TO_REAL(pdx3->value[0]), FIXED_TO_REAL(pdy3->value[0]));
#endif
}
static void Seac(XCF_Handle h, PStackValue pasb, PStackValue padx, PStackValue
pady, PStackValue pbchar, PStackValue pachar, boolean subr)
{
h->cstr.baseSeac = FIXED_TO_INT(pbchar->value[0]);
h->cstr.accentSeac = FIXED_TO_INT(pachar->value[0]);
XC_WriteT1PStackValue(h, pasb, subr);
XC_WriteT1PStackValue(h, padx, subr);
XC_WriteT1PStackValue(h, pady, subr);
XC_WriteT1PStackValue(h, pbchar, subr);
XC_WriteT1PStackValue(h, pachar, subr);
XC_WriteT1OpCode(h, t1_seac, subr);
}
static void DotSection(XCF_Handle h, boolean subr)
{
XC_WriteT1OpCode(h, tx_dotsection, subr);
#ifdef XCF_DUMP
printf("<dotsection> ");
#endif
}
static void WriteFlexCoordinate(XCF_Handle h, PStackValue pdx, PStackValue pdy,
boolean subr)
{
ShortStackValue temp;
if ((!pdx->blend) && (pdx->value[0] == 0))
{
XC_WriteT1PStackValue(h, pdy, subr);
XC_WriteT1OpCode(h, tx_vmoveto, subr);
}
else if ((!pdy->blend) && (pdy->value[0] == 0))
{
XC_WriteT1PStackValue(h, pdx, subr);
XC_WriteT1OpCode(h, tx_hmoveto, subr);
}
else
{
XC_WriteT1PStackValue(h, pdx, subr);
XC_WriteT1PStackValue(h, pdy, subr);
XC_WriteT1OpCode(h, tx_rmoveto, subr);
}
XC_WriteT1PStackValue(h, IntToPSV(&temp, 2), subr);
XC_WriteT1OpCode(h, tx_callsubr, subr);
}
static void Flex(
XCF_Handle h,
PStackValue pdx1,
PStackValue pdy1,
PStackValue pdx2,
PStackValue pdy2,
PStackValue pdx3,
PStackValue pdy3,
PStackValue pdx4,
PStackValue pdy4,
PStackValue pdx5,
PStackValue pdy5,
PStackValue pdx6,
PStackValue pdy6,
PStackValue pdx7,
PStackValue pdy7,
PStackValue pflexHeight,
PStackValue pendpointX,
PStackValue pendpointY,
boolean subr)
{
ShortStackValue temp;
XC_WriteT1PStackValue(h, IntToPSV(&temp, 1), subr);
XC_WriteT1OpCode(h, tx_callsubr, subr);
WriteFlexCoordinate(h, pdx1, pdy1, subr);
WriteFlexCoordinate(h, pdx2, pdy2, subr);
WriteFlexCoordinate(h, pdx3, pdy3, subr);
WriteFlexCoordinate(h, pdx4, pdy4, subr);
WriteFlexCoordinate(h, pdx5, pdy5, subr);
WriteFlexCoordinate(h, pdx6, pdy6, subr);
WriteFlexCoordinate(h, pdx7, pdy7, subr);
XC_WriteT1PStackValue(h, pflexHeight, subr);
XC_WriteT1PStackValue(h, pendpointX, subr);
XC_WriteT1PStackValue(h, pendpointY, subr);
XC_WriteT1PStackValue(h, PSTACKVALUE(h, SV0), subr);
XC_WriteT1OpCode(h, tx_callsubr, subr);
PSVCopy(h, h->cstr.x, pendpointX);
PSVCopy(h, h->cstr.y, pendpointY);
#ifdef XCF_DUMP
printf("<flex> ");
#endif
}
static void HStem(XCF_Handle h, PStackValue py, PStackValue pdy, boolean subr)
{
boolean hintSub = ((!CIDFONT) && (h->cstr.subrFlatten == 0) &&
(h->cstr.hints == SubrHints)) || subr;
XC_WriteT1PStackValue(h, py, hintSub);
XC_WriteT1PStackValue(h, pdy, hintSub);
XC_WriteT1OpCode(h, tx_hstem, hintSub);
h->cstr.waitingForFirstHint = false;
#ifdef XCF_DUMP
printf("%g %g <hstem> ", FIXED_TO_REAL(py->value[0]), FIXED_TO_REAL(pdy->value[0]));
#endif
}
static void VStem(XCF_Handle h, PStackValue px, PStackValue pdx, boolean subr)
{
boolean hintSub = ((!CIDFONT) && (h->cstr.subrFlatten == 0) &&
(h->cstr.hints == SubrHints)) || subr;
XC_WriteT1PStackValue(h, px, hintSub);
XC_WriteT1PStackValue(h, pdx, hintSub);
XC_WriteT1OpCode(h, tx_vstem, hintSub);
h->cstr.waitingForFirstHint = false;
#ifdef XCF_DUMP
printf("%g %g <vstem> ", FIXED_TO_REAL(px->value[0]), FIXED_TO_REAL(pdx->value[0]));
#endif
}
static void HStem3(XCF_Handle h, PStackValue py0, PStackValue pdy0, PStackValue
py1, PStackValue pdy1, PStackValue py2, PStackValue pdy2,
boolean subr)
{
boolean hintSub = ((!CIDFONT) && (h->cstr.subrFlatten == 0) &&
(h->cstr.hints == SubrHints)) || subr;
XC_WriteT1PStackValue(h, py0, hintSub);
XC_WriteT1PStackValue(h, pdy0, hintSub);
XC_WriteT1PStackValue(h, py1, hintSub);
XC_WriteT1PStackValue(h, pdy1, hintSub);
XC_WriteT1PStackValue(h, py2, hintSub);
XC_WriteT1PStackValue(h, pdy2, hintSub);
XC_WriteT1OpCode(h, t1_hstem3, hintSub);
h->cstr.waitingForFirstHint = false;
#ifdef XCF_DUMP
printf("%g %g %g %g %g %g <hstem3> ", FIXED_TO_REAL(py0->value[0]), FIXED_TO_REAL(pdy0->value[0]), FIXED_TO_REAL(py1->value[0]), FIXED_TO_REAL(pdy1->value[0]), FIXED_TO_REAL(py2->value[0]), FIXED_TO_REAL(pdy2->value[0]));
#endif
}
static void VStem3(XCF_Handle h, PStackValue px0, PStackValue pdx0, PStackValue
px1, PStackValue pdx1, PStackValue px2, PStackValue pdx2,
boolean subr)
{
boolean hintSub = ((!CIDFONT) && (h->cstr.subrFlatten == 0) &&
(h->cstr.hints == SubrHints)) || subr;
XC_WriteT1PStackValue(h, px0, hintSub);
XC_WriteT1PStackValue(h, pdx0, hintSub);
XC_WriteT1PStackValue(h, px1, hintSub);
XC_WriteT1PStackValue(h, pdx1, hintSub);
XC_WriteT1PStackValue(h, px2, hintSub);
XC_WriteT1PStackValue(h, pdx2, hintSub);
XC_WriteT1OpCode(h, t1_vstem3, hintSub);
h->cstr.waitingForFirstHint = false;
#ifdef XCF_DUMP
printf("%g %g %g %g %g %g <vstem3> ", FIXED_TO_REAL(px0->value[0]), FIXED_TO_REAL(pdx0->value[0]), FIXED_TO_REAL(px1->value[0]), FIXED_TO_REAL(pdx1->value[0]), FIXED_TO_REAL(px2->value[0]), FIXED_TO_REAL(pdx2->value[0]));
#endif
}
static void ClosePath(XCF_Handle h, boolean subr)
{
XC_WriteT1OpCode(h, t1_closepath, subr);
#ifdef XCF_DUMP
printf("<closepath> ");
#endif
}
static void EndChar(XCF_Handle h, boolean subr)
{
XC_WriteT1OpCode(h, tx_endchar, subr);
#ifdef XCF_DUMP
printf("<endchar> \n\n");
#endif
}
static void StartHintSub(XCF_Handle h, boolean subr)
{
ShortStackValue temp;
if (CIDFONT)
{
XC_WriteT1PStackValue(h, IntToPSV(&temp, 4), subr);
XC_WriteT1OpCode(h, tx_callsubr, subr);
}
else
{
if (!h->cstr.subrFlatten)
XC_WriteT1PStackValue(h, IntToPSV(&temp, h->type1.subrOffsets.cnt), subr);
XC_WriteT1PStackValue(h, IntToPSV(&temp, 4), subr);
XC_WriteT1OpCode(h, tx_callsubr, subr);
if (!h->cstr.subrFlatten)
NewT1Subr(h);
}
#ifdef XCF_DUMP
printf("[HINT SUB] ");
#endif
}
/*************************** End Basic Operations **************************/
static void WriteReversedCounterArg(XCF_Handle h, PStackValue parg, boolean subr)
{
IntX argIndex;
ShortStackValue temp;
if (h->cstr.counterBufferCount < 22)
PSVCopy(h, h->cstr.counterBuffer[h->cstr.counterBufferCount++], parg);
else
{
for (argIndex = 21; argIndex >= 0; --argIndex)
XC_WriteT1PStackValue(h, h->cstr.counterBuffer[argIndex], subr);
XC_WriteT1PStackValue(h, IntToPSV(&temp, 22), subr);
XC_WriteT1PStackValue(h, IntToPSV(&temp, 12), subr);
XC_WriteT1OpCode(h, t1_callother, subr);
PSVCopy(h, h->cstr.counterBuffer[0], parg);
h->cstr.counterBufferCount = 1;
}
}
static void FlushReversedCounterArgs(XCF_Handle h, boolean subr)
{
IntX argIndex;
ShortStackValue temp;
if (!h->cstr.counterBufferCount)
return;
for (argIndex = h->cstr.counterBufferCount-1; argIndex >= 0; --argIndex)
XC_WriteT1PStackValue(h, h->cstr.counterBuffer[argIndex], subr);
XC_WriteT1PStackValue(h, IntToPSV(&temp, h->cstr.counterBufferCount), subr);
XC_WriteT1PStackValue(h, IntToPSV(&temp, 13), subr);
XC_WriteT1OpCode(h, t1_callother, subr);
}
/* This structure is defined to store the temporary counterGroup info. */
typedef struct {
StackValue edge;
StackValue delta;
Card16 opCode;
Card32 counterGroups;
} CounterValue;
static void NewCounterValues(XCF_Handle h, void PTR_PREFIX * PTR_PREFIX *p)
{
if ( *p == 0 )
{
Card16 totalSize;
/* Allocate the data space for all the counter values that we need */
totalSize = (Card16)(sizeof(CounterValue) * MAX_HINTS);
if (!h->callbacks.allocate(p, totalSize, h->callbacks.allocateHook))
XCF_FATAL_ERROR(h, XCF_MemoryAllocationError, "CounterValue Allocation Failure.", totalSize);
h->callbacks.memset((void PTR_PREFIX *)*p, 0, totalSize);
}
}
static void WriteHorVCounters(XCF_Handle h, Card16 opCode, CardX groupCount,
boolean subr)
{
CardX hintIndex;
CardX groupIndex;
IntX argIndex;
CounterValue *counterGroup;
CardX counterGroupCount;
StackValue currentEdge;
StackValue nextEdge;
StackValue temp;
boolean firstStem;
/* Make sure that we allocate memory for our temp CounterValue. */
NewCounterValues(h, (void PTR_PREFIX * PTR_PREFIX *)&h->cstr.pCounterVal);
counterGroup = (CounterValue *)h->cstr.pCounterVal;
for (groupIndex = groupCount; groupIndex > 0; --groupIndex)
{ /* loop backwards through groups */
IntToPSV(&currentEdge, 0);
counterGroupCount = 0;
/* Gather stems into array */
for (hintIndex=0;hintIndex<h->cstr.hintCount;++hintIndex)
{
if ((h->cstr.hintMap[hintIndex].opCode == opCode) && (h->cstr.hintMap[hintIndex].counterGroups & (1 << (groupIndex - 1))))
{
/* Copy stem */
PSVCopy(h, &counterGroup[counterGroupCount].edge,
h->cstr.hintMap[hintIndex].edge);
PSVCopy(h, &counterGroup[counterGroupCount].delta,
h->cstr.hintMap[hintIndex].delta);
counterGroup[counterGroupCount].opCode =
h->cstr.hintMap[hintIndex].opCode;
counterGroup[counterGroupCount].counterGroups =
h->cstr.hintMap[hintIndex].counterGroups;
/* Find trailing edge for next delta. */
PSVAdd(h, &nextEdge, &counterGroup[counterGroupCount].edge,
&counterGroup[counterGroupCount].delta);
PSVCopy(h, &temp, &counterGroup[counterGroupCount].edge);
PSVSubtract(h, &counterGroup[counterGroupCount].edge, &temp, &currentEdge); /* turn leading edge into delta */
PSVCopy(h, &currentEdge, &nextEdge); /* save trailing edge calculate delta for next stem */
++counterGroupCount;
}
}
/* write out stems backwards */
firstStem = true;
for (argIndex = counterGroupCount-1; argIndex >= 0; --argIndex)
{
if (firstStem)
{
IntToPSV(&temp, 0);
PSVSubtract(h, &currentEdge, &temp, &counterGroup[argIndex].delta);
WriteReversedCounterArg(h, &currentEdge, subr);
PSVAdd(h, &currentEdge, &counterGroup[argIndex].edge, &counterGroup[argIndex].delta);
WriteReversedCounterArg(h, &currentEdge, subr);
firstStem = false;
}
else
{
WriteReversedCounterArg(h, &counterGroup[argIndex].delta, subr);
WriteReversedCounterArg(h, &counterGroup[argIndex].edge, subr);
}
}
}
WriteReversedCounterArg(h, IntToPSV(&currentEdge, groupCount), subr);
}
static void WriteCounters(XCF_Handle h, boolean subr)
{
h->cstr.counterBufferCount = 0; /* Clear counter buffer */
WriteHorVCounters(h, tx_vstem, h->cstr.counterGroupVCount, subr);
WriteHorVCounters(h, tx_hstem, h->cstr.counterGroupHCount, subr);
FlushReversedCounterArgs(h, subr);
}
static void WriteHints(XCF_Handle h, boolean all, boolean subr)
{
Card16 hintIndex;
Card8 currentByte;
Card8 currentBit = 0;
HintValue hstem3Args[3];
HintValue vstem3Args[3];
Card8 hstem3ArgCount = 0;
Card8 vstem3ArgCount = 0;
for (hintIndex=0;hintIndex<h->cstr.hintCount;++hintIndex)
{
if ((!all) && (!currentBit))
{
currentByte = *h->inBuffer.pos++;
currentBit = 0x080;
}
if ((all) || (currentByte & currentBit))
{
/* cstr.languageGroup is set for each charstring in xcf_cff.c/ProcessCharStrings. */
if ((h->cstr.hintMap[hintIndex].counterGroups) && (h->cstr.languageGroup == 0))
{
if (h->cstr.hintMap[hintIndex].opCode == tx_hstem)
{
if (hstem3ArgCount >= 3)
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Too many counters for hstem3", hstem3ArgCount );
hstem3Args[hstem3ArgCount++] = h->cstr.hintMap[hintIndex];
}
else
{
if (vstem3ArgCount >= 3)
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Too many counters for vstem3", vstem3ArgCount );
vstem3Args[vstem3ArgCount++] = h->cstr.hintMap[hintIndex];
}
}
else
{
if (h->cstr.hintMap[hintIndex].opCode == tx_hstem)
HStem(h, h->cstr.hintMap[hintIndex].edge,
h->cstr.hintMap[hintIndex].delta, subr);
else
VStem(h, h->cstr.hintMap[hintIndex].edge,
h->cstr.hintMap[hintIndex].delta, subr);
}
}
currentBit = currentBit>>1;
}
if (hstem3ArgCount == 3)
HStem3(h, hstem3Args[0].edge, hstem3Args[0].delta, hstem3Args[1].edge,
hstem3Args[1].delta, hstem3Args[2].edge, hstem3Args[2].delta, subr);
else if (hstem3ArgCount == 1)
HStem(h, hstem3Args[0].edge, hstem3Args[0].delta, subr);
else if (hstem3ArgCount == 2)
{
HStem(h, hstem3Args[0].edge, hstem3Args[0].delta, subr);
HStem(h, hstem3Args[1].edge, hstem3Args[1].delta, subr);
}
else if (hstem3ArgCount > 3)
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "hstem3 argument count is greater than 3", hstem3ArgCount );
if (vstem3ArgCount == 3)
VStem3(h, vstem3Args[0].edge, vstem3Args[0].delta, vstem3Args[1].edge,
vstem3Args[1].delta, vstem3Args[2].edge, vstem3Args[2].delta, subr);
else if (vstem3ArgCount == 1)
VStem(h, vstem3Args[0].edge, vstem3Args[0].delta, subr);
else if (vstem3ArgCount == 2)
{
VStem(h, vstem3Args[0].edge, vstem3Args[0].delta, subr);
VStem(h, vstem3Args[1].edge, vstem3Args[1].delta, subr);
}
else if (vstem3ArgCount > 3)
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "vstem3 argument count is greater than 3", vstem3ArgCount );
}
static void StateChange(XCF_Handle h,
enum PenStateTransition penTran,
enum HintStateTransition hintTran,
boolean triggerHsbw,
unsigned int expectedArgumentCount,
boolean subr)
{
Card16 stackIndex;
StackValue svx;
switch (penTran)
{
case ToPenUp :
if (h->cstr.pen == PenDown)
ClosePath(h, subr);
h->cstr.pen = PenUp;
break;
case ToPenDown :
if (h->cstr.pen == PenNull)
{
/* Make sure all contours start with a move */
RMoveTo(h, PSTACKVALUE(h, SV0), PSTACKVALUE(h, SV0), subr);
}
h->cstr.pen = PenDown;
break;
case NoPenEffect :
break;
}
switch (hintTran)
{
case ToNotInHints :
if (h->cstr.hints == InitialHints)
{
if ((h->cstr.languageGroup != 0) && (h->cstr.counterGroupCount))
WriteCounters(h, subr);
WriteHints(h, true, subr);
}
h->cstr.hints = NotInHints;
break;
case ToInitialHints :
h->cstr.hints = InitialHints;
break;
case ToSubrHints :
h->cstr.hints = SubrHints;
break;
case NoHintEffect :
break;
}
if (h->cstr.waitingForHsbw && triggerHsbw)
{
h->cstr.waitingForHsbw = false;
if (h->cstr.stackTop <= expectedArgumentCount)
{
/* Currently, subr is true only when processing a transitional
design character. These characters have the hsbw defined in
their charstring and therefore hsbw should not be included
in the subr definition.
*/
if (!subr)
{
FixedToPSV(&svx, h->dict.defaultWidthX);
Hsbw(h, PSTACKVALUE(h, SV0), &svx, subr);
}
}
else
{
PSVCopy(h, &svx, h->cstr.stack[0]);
PSVRealAdd(h, &svx, h->dict.nominalWidthX);
Hsbw(h, PSTACKVALUE(h, SV0), &svx, subr);
if (h->cstr.stackTop < 1)
XCF_FATAL_ERROR(h, XCF_StackUnderflow, "Stack Underflow In hsbw ", h->cstr.stackTop );
for (stackIndex = 0; stackIndex<h->cstr.stackTop-1; ++stackIndex)
/* remove first item and shift stack */
PSVCopy(h, h->cstr.stack[stackIndex], h->cstr.stack[stackIndex+1]);
--h->cstr.stackTop;
}
}
}
static void AddToHintMap(XCF_Handle h, Card16 opCode)
{
StackValue y;
StackValue dy;
StackValue temp;
Card16 opIndex;
Card16 index = 0;
IntToPSV(&temp, 0);
for (opIndex=1;opIndex<=h->cstr.stackTop/2;++opIndex)
{
if (h->cstr.hintCount == MAX_HINTS)
XCF_FATAL_ERROR(h, XCF_HintOverflow, "Hint Overflow", h->cstr.hintCount);
PSVAdd(h, &y, &temp, h->cstr.stack[index++]);
PSVCopy(h, &dy, h->cstr.stack[index++]);
PSVCopy(h, h->cstr.hintMap[h->cstr.hintCount].edge, &y);
PSVCopy(h, h->cstr.hintMap[h->cstr.hintCount].delta, &dy);
h->cstr.hintMap[h->cstr.hintCount].opCode = opCode;
h->cstr.hintMap[h->cstr.hintCount].counterGroups = 0;
PSVCopy(h, &temp, &y);
PSVAdd(h, &y, &temp, &dy);
PSVCopy(h, &temp, &y);
++h->cstr.hintCount;
}
}
void XC_WriteHMoveTo(XCF_Handle h, boolean subr)
{
StateChange(h, ToPenUp, ToNotInHints, true, 1, subr);
RMoveTo(h, h->cstr.stack[0], PSTACKVALUE(h, SV0), subr);
}
void XC_WriteVMoveTo(XCF_Handle h, boolean subr)
{
StateChange(h, ToPenUp, ToNotInHints, true, 1, subr);
RMoveTo(h, PSTACKVALUE(h,SV0), h->cstr.stack[0], subr);
}
void XC_WriteRMoveTo(XCF_Handle h, boolean subr)
{
StateChange(h, ToPenUp, ToNotInHints, true, 2, subr);
RMoveTo(h, h->cstr.stack[0], h->cstr.stack[1], subr);
}
void XC_WriteRLineTo(XCF_Handle h, boolean subr)
{
Card16 stackIndex = 0;
Card16 opIndex;
Card16 repeatCount = h->cstr.stackTop/2;
StateChange(h, ToPenDown, ToNotInHints, false, 0, subr);
for (opIndex=1;opIndex<=repeatCount;++opIndex)
{
RLineTo(h, h->cstr.stack[stackIndex], h->cstr.stack[stackIndex+1], subr);
stackIndex += 2;
}
}
void XC_WriteHLineToAndVLineTo(XCF_Handle h, boolean hLine, boolean subr)
{
Card16 opIndex;
StateChange(h, ToPenDown, ToNotInHints, false, 0, subr);
for (opIndex=1;opIndex<=h->cstr.stackTop;++opIndex)
{
if (hLine)
RLineTo(h, h->cstr.stack[opIndex-1], PSTACKVALUE(h, SV0), subr);
else
RLineTo(h, PSTACKVALUE(h, SV0), h->cstr.stack[opIndex-1], subr);
hLine = !hLine;
}
}
static void WriteSingleRRCurveTo(XCF_Handle h,
PStackValue pdx1,
PStackValue pdy1,
PStackValue pdx2,
PStackValue pdy2,
PStackValue pdx3,
PStackValue pdy3,
boolean subr)
{
StateChange(h, ToPenDown, ToNotInHints, false, 0, subr);
RRCurveTo(h, pdx1, pdy1, pdx2, pdy2, pdx3, pdy3, subr);
}
void XC_WriteRRCurveTo(XCF_Handle h, boolean subr)
{
Card16 stackIndex = 0;
Card16 opIndex;
Card16 repeatCount = h->cstr.stackTop/6;
for (opIndex=1;opIndex<=repeatCount;++opIndex)
{
WriteSingleRRCurveTo(h,
h->cstr.stack[stackIndex],
h->cstr.stack[stackIndex+1],
h->cstr.stack[stackIndex+2],
h->cstr.stack[stackIndex+3],
h->cstr.stack[stackIndex+4],
h->cstr.stack[stackIndex+5],
subr);
stackIndex+=6;
}
}
void XC_WriteEndChar(XCF_Handle h, boolean subr)
{
if (h->cstr.stackTop >= 4)
{
StateChange(h, NoPenEffect, NoHintEffect, true, 4, subr);
Seac(h,
PSTACKVALUE(h, SV0),
h->cstr.stack[0],
h->cstr.stack[1],
h->cstr.stack[2],
h->cstr.stack[3],
subr);
}
else
{
StateChange(h, ToPenUp, ToNotInHints, true, 0, subr);
if (h->cstr.stackTop == 0)
EndChar(h, subr);
else
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Arguments Left On Stack At endchar ", h->cstr.stackTop );
}
}
void XC_WriteRCurveLine(XCF_Handle h, boolean subr)
{
Card16 stackIndex = 0;
while (stackIndex + 2 < h->cstr.stackTop)
{
WriteSingleRRCurveTo(h,
h->cstr.stack[stackIndex],
h->cstr.stack[stackIndex+1],
h->cstr.stack[stackIndex+2],
h->cstr.stack[stackIndex+3],
h->cstr.stack[stackIndex+4],
h->cstr.stack[stackIndex+5],
subr);
stackIndex+=6;
}
if (stackIndex + 2 <= h->cstr.stackTop)
{
RLineTo(h, h->cstr.stack[stackIndex], h->cstr.stack[stackIndex+1], subr);
}
}
void XC_WriteRLineCurve(XCF_Handle h, boolean subr)
{
Card16 stackIndex = 0;
StateChange(h, ToPenDown, ToNotInHints, false, 0, subr);
while (stackIndex + 6 < h->cstr.stackTop)
{
RLineTo(h, h->cstr.stack[stackIndex], h->cstr.stack[stackIndex+1], subr);
stackIndex += 2;
}
if (stackIndex + 6 <= h->cstr.stackTop)
WriteSingleRRCurveTo(h,
h->cstr.stack[stackIndex],
h->cstr.stack[stackIndex+1],
h->cstr.stack[stackIndex+2],
h->cstr.stack[stackIndex+3],
h->cstr.stack[stackIndex+4],
h->cstr.stack[stackIndex+5],
subr);
}
void XC_WriteVVCurveTo(XCF_Handle h, boolean subr)
{
Card16 stackIndex = 0;
if (h->cstr.stackTop & 0x01) /* If odd number of arguments */
{
WriteSingleRRCurveTo(h,
h->cstr.stack[0],
h->cstr.stack[1],
h->cstr.stack[2],
h->cstr.stack[3],
PSTACKVALUE(h, SV0),
h->cstr.stack[4],
subr);
stackIndex = 5;
}
while (stackIndex + 4 <= h->cstr.stackTop)
{
WriteSingleRRCurveTo(h,
PSTACKVALUE(h, SV0),
h->cstr.stack[stackIndex],
h->cstr.stack[stackIndex+1],
h->cstr.stack[stackIndex+2],
PSTACKVALUE(h, SV0),
h->cstr.stack[stackIndex+3],
subr);
stackIndex+=4;
}
}
void XC_WriteHHCurveTo(XCF_Handle h, boolean subr)
{
Card16 stackIndex = 0;
if (h->cstr.stackTop & 0x01) /* If odd number of arguments */
{
WriteSingleRRCurveTo(h,
h->cstr.stack[1],
h->cstr.stack[0],
h->cstr.stack[2],
h->cstr.stack[3],
h->cstr.stack[4],
PSTACKVALUE(h, SV0),
subr);
stackIndex = 5;
}
while (stackIndex + 4 <= h->cstr.stackTop)
{
WriteSingleRRCurveTo(h,
h->cstr.stack[stackIndex],
PSTACKVALUE(h, SV0),
h->cstr.stack[stackIndex+1],
h->cstr.stack[stackIndex+2],
h->cstr.stack[stackIndex+3],
PSTACKVALUE(h, SV0),
subr);
stackIndex+=4;
}
}
void XC_WriteHVorVHCurveTo(XCF_Handle h, boolean hvCurve, boolean subr)
{
Card16 stackIndex = 0;
while (stackIndex + 4 <= h->cstr.stackTop)
{
if (stackIndex + 5 == h->cstr.stackTop)
{
if (hvCurve)
WriteSingleRRCurveTo(h,
h->cstr.stack[stackIndex],
PSTACKVALUE(h, SV0),
h->cstr.stack[stackIndex+1],
h->cstr.stack[stackIndex+2],
h->cstr.stack[stackIndex+4],
h->cstr.stack[stackIndex+3],
subr);
else
WriteSingleRRCurveTo(h,
PSTACKVALUE(h, SV0),
h->cstr.stack[stackIndex],
h->cstr.stack[stackIndex+1],
h->cstr.stack[stackIndex+2],
h->cstr.stack[stackIndex+3],
h->cstr.stack[stackIndex+4],
subr);
stackIndex+=5;
}
else
{
StateChange(h, ToPenDown, ToNotInHints, false, 0, subr);
if (hvCurve)
{
RRCurveTo(h,
h->cstr.stack[stackIndex],
PSTACKVALUE(h, SV0),
h->cstr.stack[stackIndex+1],
h->cstr.stack[stackIndex+2],
PSTACKVALUE(h, SV0),
h->cstr.stack[stackIndex+3],
subr);
}
else
{
RRCurveTo(h,
PSTACKVALUE(h, SV0),
h->cstr.stack[stackIndex],
h->cstr.stack[stackIndex+1],
h->cstr.stack[stackIndex+2],
h->cstr.stack[stackIndex+3],
PSTACKVALUE(h, SV0),
subr);
}
hvCurve = !hvCurve;
stackIndex+=4;
}
}
}
static Fixed AbsoluteValue(Fixed f)
{
if (f < 0)
return -f;
else
return f;
}
static void WriteExpandedFlexCurveTo(XCF_Handle h,
PStackValue pdx2,
PStackValue pdy2,
PStackValue pdx3,
PStackValue pdy3,
PStackValue pdx4,
PStackValue pdy4,
PStackValue pdx5,
PStackValue pdy5,
PStackValue pdx6,
PStackValue pdy6,
PStackValue pdx7,
PStackValue pdy7,
PStackValue pflexHeight,
boolean subr)
{
StackValue endpointX;
StackValue endpointY;
StackValue refX, refY; /* reference point */
StackValue dx1, dy1; /* first two arguments passed to flex */
StackValue temp, temp1;
PSVAdd7(h,&endpointX,h->cstr.x,pdx2,pdx3,pdx4,pdx5,pdx6,pdx7);
PSVAdd7(h,&endpointY,h->cstr.y,pdy2,pdy3,pdy4,pdy5,pdy6,pdy7);
h->cstr.flexUsed = true;
if (AbsoluteValue(endpointX.value[0] - h->cstr.x->value[0]) > AbsoluteValue(endpointY.value[0] - h->cstr.y->value[0])) /* horizontal */
{
PSVAdd4(h,&refX,h->cstr.x,pdx2,pdx3,pdx4);
PSVAdd7(h,&refY,h->cstr.y,pdy2,pdy3,pdy4,pdy5,pdy6,pdy7);
}
else
{
PSVAdd7(h,&refX,h->cstr.x,pdx2,pdx3,pdx4,pdx5,pdx6,pdx7);
PSVAdd4(h,&refY,h->cstr.y,pdy2,pdy3,pdy4);
}
PSVSubtract(h, &dx1, &refX, h->cstr.x);
PSVSubtract(h, &dy1, &refY, h->cstr.y);
PSVSubtract(h, &temp, h->cstr.x, &refX);
PSVCopy(h, &temp1, pdx2);
PStackValueAdd(h, pdx2, &temp1, &temp);
PSVSubtract(h, &temp, h->cstr.y, &refY);
PSVCopy(h, &temp1, pdy2);
PStackValueAdd(h, pdy2, &temp1, &temp);
StateChange(h, ToPenDown, ToNotInHints, false, 0, subr);
Flex(h, &dx1, &dy1, pdx2, pdy2, pdx3, pdy3, pdx4, pdy4, pdx5, pdy5, pdx6,
pdy6, pdx7, pdy7, pflexHeight, &endpointX, &endpointY, subr);
}
void XC_WriteFlex(XCF_Handle h, boolean subr)
{
if (h->cstr.stackTop == 13)
{
WriteExpandedFlexCurveTo(h,
h->cstr.stack[0],
h->cstr.stack[1],
h->cstr.stack[2],
h->cstr.stack[3],
h->cstr.stack[4],
h->cstr.stack[5],
h->cstr.stack[6],
h->cstr.stack[7],
h->cstr.stack[8],
h->cstr.stack[9],
h->cstr.stack[10],
h->cstr.stack[11],
h->cstr.stack[12],
subr);
}
else
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Incorrect Argument Count For flex ", h->cstr.stackTop );
}
void XC_WriteFlex1(XCF_Handle h, boolean subr)
{
StackValue lastControlPointX, lastControlPointY;
StackValue dx, dy;
StackValue lastCtrlDx, lastCtrlDy;
if (h->cstr.stackTop != 11)
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Incorrect Argument Count For flex1 ", h->cstr.stackTop );
PSVAdd5(h,&lastCtrlDx,h->cstr.stack[0],h->cstr.stack[2],h->cstr.stack[4],h->cstr.stack[6],h->cstr.stack[8]);
PSVAdd5(h,&lastCtrlDy,h->cstr.stack[1],h->cstr.stack[3],h->cstr.stack[5],h->cstr.stack[7],h->cstr.stack[9]);
PSVAdd(h,&lastControlPointX,h->cstr.x, &lastCtrlDx);
PSVAdd(h,&lastControlPointY, h->cstr.y, &lastCtrlDy);
if (AbsoluteValue(lastCtrlDx.value[0]) > AbsoluteValue(lastCtrlDy.value[0]))
{
PSVCopy(h, &dx, h->cstr.stack[10]);
PSVSubtract(h, &dy, PSTACKVALUE(h, SV0), &lastCtrlDy);
}
else
{
PSVSubtract(h, &dx, PSTACKVALUE(h, SV0), &lastCtrlDx);
PSVCopy(h, &dy, h->cstr.stack[10]);
}
WriteExpandedFlexCurveTo(h,
h->cstr.stack[0],
h->cstr.stack[1],
h->cstr.stack[2],
h->cstr.stack[3],
h->cstr.stack[4],
h->cstr.stack[5],
h->cstr.stack[6],
h->cstr.stack[7],
h->cstr.stack[8],
h->cstr.stack[9],
&dx,
&dy,
PSTACKVALUE(h, SV50),
subr);
}
void XC_WriteHFlex(XCF_Handle h, boolean subr)
{
if (h->cstr.stackTop == 7)
{
PSVSubtract(h, PSTACKVALUE(h, SVTEMP), PSTACKVALUE(h, SV0),
h->cstr.stack[2]);
WriteExpandedFlexCurveTo(h,
h->cstr.stack[0],
PSTACKVALUE(h, SV0),
h->cstr.stack[1],
h->cstr.stack[2],
h->cstr.stack[3],
PSTACKVALUE(h, SV0),
h->cstr.stack[4],
PSTACKVALUE(h, SV0),
h->cstr.stack[5],
PSTACKVALUE(h, SVTEMP),
h->cstr.stack[6],
PSTACKVALUE(h, SV0),
PSTACKVALUE(h, SV50),
subr);
}
else
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Incorrect Argument Count For hflex ", h->cstr.stackTop );
}
void XC_WriteHFlex1(XCF_Handle h, boolean subr)
{
StackValue temp, temp1;
if (h->cstr.stackTop == 9)
{
PSVSubtract(h, &temp, PSTACKVALUE(h, SV0), h->cstr.stack[1]);
PSVSubtract(h, &temp1, &temp, h->cstr.stack[3]);
PSVSubtract(h, PSTACKVALUE(h, SVTEMP), &temp1, h->cstr.stack[7]);
WriteExpandedFlexCurveTo(h,
h->cstr.stack[0],
h->cstr.stack[1],
h->cstr.stack[2],
h->cstr.stack[3],
h->cstr.stack[4],
PSTACKVALUE(h, SV0),
h->cstr.stack[5],
PSTACKVALUE(h, SV0),
h->cstr.stack[6],
h->cstr.stack[7],
h->cstr.stack[8],
PSTACKVALUE(h, SVTEMP),
PSTACKVALUE(h, SV50),
subr);
}
else
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Incorrect Argument Count For hflex1 ", h->cstr.stackTop );
}
void XC_WriteDotSection(XCF_Handle h, boolean subr)
{
if (h->cstr.stackTop != 0)
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Arguments On Stack For dotsection ", h->cstr.stackTop );
StateChange(h, ToPenUp, ToNotInHints, false, 0, subr);
DotSection(h, subr);
}
void XC_WriteVStem(XCF_Handle h, boolean subr)
{
StateChange(h, NoPenEffect, NoHintEffect, true,
h->cstr.stackTop-(h->cstr.stackTop & 0x01), subr);
AddToHintMap(h, tx_vstem);
}
void XC_WriteHStem(XCF_Handle h, boolean subr)
{
StateChange(h, NoPenEffect, NoHintEffect, true,
h->cstr.stackTop-(h->cstr.stackTop & 0x01), subr);
AddToHintMap(h, tx_hstem);
}
void XC_WriteHintMask(XCF_Handle h, boolean subr)
{
if (h->cstr.stackTop > 0) /* If stack is not empty then implied VStem */
XC_WriteVStem(h, subr);
if ((h->cstr.hints == InitialHints) && (h->cstr.languageGroup != 0) && (h->cstr.counterGroupCount))
WriteCounters(h, subr);
if (h->cstr.waitingForFirstHint) /* In case inital hints aren't at beginning of char string */
h->cstr.hints = InitialHints;
else
{
h->cstr.hints = SubrHints;
StartHintSub(h, subr);
}
WriteHints(h, false, subr);
h->cstr.hints = SubrHints;
}
void XC_SetCounters(XCF_Handle h, boolean subr)
{
Card16 hintIndex;
Card8 currentByte;
Card8 currentBit = 0;
if (h->cstr.stackTop > 0) /* If stack is not empty then implied VStem */
XC_WriteVStem(h, subr);
for (hintIndex=0;hintIndex<h->cstr.hintCount;++hintIndex)
{
if (!currentBit)
{
currentByte = *h->inBuffer.pos++;
currentBit = 0x080;
}
if (currentByte & currentBit)
{
if (h->cstr.counterGroupCount >= MAX_COUNTER_GROUPS)
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Too many counter groups ", h->cstr.counterGroupCount );
h->cstr.hintMap[hintIndex].counterGroups |= 1 << h->cstr.counterGroupCount;
if (h->cstr.hintMap[hintIndex].opCode == tx_hstem)
h->cstr.counterGroupHCount = h->cstr.counterGroupCount+1;
else /* tx_vstem */
h->cstr.counterGroupVCount = h->cstr.counterGroupCount+1;
}
currentBit = currentBit>>1;
}
++h->cstr.counterGroupCount;
}
#if JUDY
static void Blend(XCF_Handle h)
{
CardX numberOfValues;
CardX numberOfBlends;
CardX stackIndex;
CardX blendStackIndex;
CardX i,j;
if (h->cstr.stackTop == 0)
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Stack empty during blend operation ", h->cstr.stackTop );
--h->cstr.stackTop;
numberOfBlends = h->cstr.stack[h->cstr.stackTop].value[0];
numberOfValues = h->dict.numberOfMasters * numberOfBlends;
if (h->cstr.stackTop < numberOfValues)
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Stack underflow during blend operation ", h->cstr.stackTop );
stackIndex = h->cstr.stackTop - numberOfValues;
blendStackIndex = stackIndex;
for (i=0; i<numberOfBlends; ++i)
{
for (j=0; j< (CardX)h->dict.numberOfMasters; ++j)
h->cstr.stack[blendStackIndex].value[j] = h->cstr.stack[stackIndex++].value[0];
h->cstr.stack[blendStackIndex].blend = true;
++blendStackIndex;
}
h->cstr.stackTop = blendStackIndex;
}
#endif /* JUDY */
static void Translate(XCF_Handle h, boolean subr)
{
switch (h->cstr.opCode)
{
case tx_hstem :
case t2_hstemhm : XC_WriteHStem(h, subr);
break;
case tx_vstem :
case t2_vstemhm : XC_WriteVStem(h, subr);
break;
case tx_hmoveto : XC_WriteHMoveTo(h, subr);
break;
case tx_vmoveto : XC_WriteVMoveTo(h, subr);
break;
case tx_rlineto : XC_WriteRLineTo(h, subr);
break;
case tx_hlineto : XC_WriteHLineToAndVLineTo(h, true, subr);
break;
case tx_vlineto : XC_WriteHLineToAndVLineTo(h, false, subr);
break;
case tx_rrcurveto : XC_WriteRRCurveTo(h, subr);
break;
case tx_endchar : XC_WriteEndChar(h, subr);
break;
case tx_rmoveto : XC_WriteRMoveTo(h, subr);
break;
case t2_rcurveline : XC_WriteRCurveLine(h, subr);
break;
case t2_rlinecurve : XC_WriteRLineCurve(h, subr);
break;
case t2_vvcurveto : XC_WriteVVCurveTo(h, subr);
break;
case t2_hhcurveto : XC_WriteHHCurveTo(h, subr);
break;
case tx_vhcurveto : XC_WriteHVorVHCurveTo(h, false, subr);
break;
case tx_hvcurveto : XC_WriteHVorVHCurveTo(h, true, subr);
break;
case tx_dotsection : XC_WriteDotSection(h, subr);
break;
case t2_flex : XC_WriteFlex(h, subr);
break;
case t2_flex1 : XC_WriteFlex1(h, subr);
break;
case t2_hflex : XC_WriteHFlex(h, subr);
break;
case t2_hflex1 : XC_WriteHFlex1(h, subr);
break;
case t2_hintmask : XC_WriteHintMask(h, subr);
break;
case t2_cntrmask : XC_SetCounters(h, subr);
break;
/* The following opcodes can be found in certain mmfonts. */
case tx_add:
case tx_sub:
case tx_load:
case tx_get:
case tx_put:
case tx_store:
case tx_ifelse:
{
Card16 j;
for (j = 0; j < h->cstr.stackTop; j++)
XC_WriteT1PStackValue(h, h->cstr.stack[j], subr);
XC_WriteT1OpCode(h, h->cstr.opCode, subr);
}
break;
default :
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Unrecognized Operator",
h->cstr.opCode );
break;
}
h->cstr.stackTop = 0;
}
static void CopyArgumentsToStack(XCF_Handle h, Card8 PTR_PREFIX *pArgList, IntX argCount, boolean blend)
{
IntX stackIndex;
IntX blendArg;
IntX deltaIndex;
IntX i;
IntX j;
for (stackIndex= (IntX)h->cstr.stackTop; stackIndex < (IntX)h->cstr.stackTop + argCount; ++stackIndex)
{
h->cstr.stack[stackIndex]->value[0] = XCF_ArgPtrToFixed(h, &pArgList, false);
h->cstr.stack[stackIndex]->blend = false;
}
h->cstr.stackTop += (Card16)argCount;
if (blend)
{
--h->cstr.stackTop;
blendArg = FIXED_TO_INT(h->cstr.stack[h->cstr.stackTop]->value[0]);
stackIndex = h->cstr.stackTop - (blendArg * h->dict.numberOfMasters);
deltaIndex = stackIndex + blendArg;
for (i=stackIndex;i<stackIndex+blendArg;++i)
{
h->cstr.stack[i]->blend = true;
for (j=1;j<h->dict.numberOfMasters;++j)
h->cstr.stack[i]->value[j] = h->cstr.stack[deltaIndex++]->value[0] + h->cstr.stack[i]->value[0];
}
h->cstr.stackTop = stackIndex + blendArg;
}
}
static void ProcessCharstr(XCF_Handle h, unsigned int depth, boolean PTR_PREFIX
*endcharFound, boolean subr)
{
Card8 PTR_PREFIX *argList;
IntX argCount;
if (depth == 0)
{
h->cstr.stackTop = 0;
h->cstr.pen = PenNull;
}
if (depth > TX_MAX_CALL_STACK)
XCF_FATAL_ERROR(h, XCF_SubrDepthOverflow, "Maximum Subr Depth Exceeded", depth );
while (h->inBuffer.pos < h->inBuffer.end)
{
argList = h->inBuffer.pos;
argCount = XCF_FindNextOperator(h, &h->cstr.opCode, false);
if ((h->cstr.stackTop + argCount) > MAX_OPERAND_STACK)
XCF_FATAL_ERROR(h, XCF_StackOverflow, "Charstring Stack Overflow", h->cstr.stackTop + argCount );
CopyArgumentsToStack(h, argList, argCount, (h->cstr.opCode == t2_blend));
switch (h->cstr.opCode)
{
case tx_return:
if (depth == 0)
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Subr Return Encountered While Not In Subr", tx_return );
return;
break;
case tx_callsubr:
/* Make sure the stack isn't empty then flatten the subroutine. */
if (h->cstr.stackTop == 0)
XCF_FATAL_ERROR(h, XCF_StackUnderflow, "No subr number associated with subr call", 0);
else /* flatten the subroutine */
FlattenSubr(h, depth + 1, endcharFound, true);
break;
case t2_callgsubr:
if (h->cstr.stackTop == 0)
XCF_FATAL_ERROR(h, XCF_StackUnderflow, "No subr number associated with subr call", 0);
else
FlattenSubr(h, depth + 1, endcharFound, false);
break;
case t2_blend : /* Do Nothing and loop again */
break;
default:
Translate(h, subr);
break;
} /* end case */
if (h->cstr.opCode == tx_endchar)
{
*endcharFound = true;
return;
}
} /* end while */
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Charstring Not Terminated With endchar", 0 );
}
/* This is called recursively from ProcessCharstr to flatten subroutines. */
static void FlattenSubr(XCF_Handle h, unsigned int depth, boolean PTR_PREFIX
*endcharFound, boolean localSubr)
{
Card16 subrNum;
Card16 pos;
InBufferStruct inBuffer;
if ((localSubr && h->dict.localSubrs.count == 0) ||
(!localSubr && h->fontSet.globalSubrs.count == 0))
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "No subrs defined but subr called in charstring", 0);
/* Save value of inBuffer. */
h->callbacks.memcpy(&inBuffer, (Card8 PTR_PREFIX *)&h->inBuffer, (Card16)
sizeof(InBufferStruct));
pos = (Card16)(h->inBuffer.pos - h->inBuffer.start); /* position relative to start */
subrNum = FIXED_TO_INT(h->cstr.stack[h->cstr.stackTop-1]->value[0]) + (localSubr ? h->dict.localSubrBias : h->fontSet.globalSubrBias);
XCF_LookUpTableEntry(h, (localSubr ? &h->dict.localSubrs : &h->fontSet.globalSubrs), subrNum);
--h->cstr.stackTop; /* Remove subr number from stack. */
ProcessCharstr(h, depth, endcharFound, false);
/* Restore value of inBuffer. */
XCF_ReadBlock(h, inBuffer.blockOffset, inBuffer.blockLength);
h->inBuffer.pos = h->inBuffer.start + pos;
}
void XC_SetUpStandardSubrs(XCF_Handle h)
{
ShortStackValue temp;
/* dup 0 ## -| { 3 0 callother pop pop setcurrentpoint return } */
NewT1Subr(h);
XC_WriteT1PStackValue(h, IntToPSV(&temp, 3), true);
XC_WriteT1PStackValue(h, PSTACKVALUE(h, SV0), true);
XC_WriteT1OpCode(h, t1_callother, true);
XC_WriteT1OpCode(h, t1_pop, true);
XC_WriteT1OpCode(h, t1_pop, true);
XC_WriteT1OpCode(h, t1_setcurrentpt, true);
/* dup 1 ## -| { 0 1 callother return } | */
NewT1Subr(h);
XC_WriteT1PStackValue(h, PSTACKVALUE(h, SV0), true);
XC_WriteT1PStackValue(h, IntToPSV(&temp, 1), true);
XC_WriteT1OpCode(h, t1_callother, true);
/* dup 2 ## -| { 0 2 callother return } | */
NewT1Subr(h);
XC_WriteT1PStackValue(h, PSTACKVALUE(h, SV0), true);
XC_WriteT1PStackValue(h, IntToPSV(&temp, 2), true);
XC_WriteT1OpCode(h, t1_callother, true);
/* dup 3 ## -| { return } | */
NewT1Subr(h);
/* dup 4 ## -| { <<3>> 1 3 callother pop callsubr return } */
NewT1Subr(h);
if (CIDFONT || h->options.subrFlatten)
XC_WriteT1PStackValue(h, IntToPSV(&temp, 3), true);
XC_WriteT1PStackValue(h, IntToPSV(&temp, 1), true);
XC_WriteT1PStackValue(h, IntToPSV(&temp, 3), true);
XC_WriteT1OpCode(h, t1_callother, true);
XC_WriteT1OpCode(h, t1_pop, true);
XC_WriteT1OpCode(h, tx_callsubr, true);
/* dup 5 ## -| { return } | */
NewT1Subr(h);
/* Last subr in a CIDFont is 4; the call to NewT1Subr above closes out the DA. */
if (CIDFONT || !h->dict.numberOfMasters)
return;
/* dup 6 ## -| { 2 14 callother pop return } | */
NewT1Subr(h);
XC_WriteT1PStackValue(h, IntToPSV(&temp, h->dict.numberOfMasters), true);
XC_WriteT1PStackValue(h, IntToPSV(&temp, 14), true);
XC_WriteT1OpCode(h, t1_callother, true);
XC_WriteT1OpCode(h, t1_pop, true);
}
static void InitStackVal(XCF_Handle h)
{
Card16 i;
Card16 svSize;
Card8 *p;
Card16 offset;
NewStackValues(h, (void PTR_PREFIX * PTR_PREFIX *)&p, NUM_STACK_VALUES, &svSize);
h->cstr.pstackVal = (PStackValue)p;
offset = 0;
h->cstr.x = NEXTSTACKVALUE(p, offset, svSize);
h->cstr.y = NEXTSTACKVALUE(p, offset, svSize);
for (i=0; i < MAX_OPERAND_STACK; i++)
{
h->cstr.stack[i] = NEXTSTACKVALUE(p, offset, svSize);
}
for (i=0; i < MAX_COUNTER_BUFFER; i++)
{
h->cstr.counterBuffer[i] = NEXTSTACKVALUE(p, offset, svSize);
}
for (i=0; i < MAX_HINTS; i++)
{
h->cstr.hintMap[i].delta = NEXTSTACKVALUE(p, offset, svSize);
h->cstr.hintMap[i].edge = NEXTSTACKVALUE(p, offset, svSize);
}
for (i=0; i < MAX_SVTEMP; i++)
{
h->cstr.psvTemp[i] = NEXTSTACKVALUE(p, offset, svSize);
}
IntToPSV(PSTACKVALUE(h, SV0), 0);
IntToPSV(PSTACKVALUE(h, SV50), 50);
}
void XC_Init(XCF_Handle h)
{
h->cstr.flexUsed = false;
InitStackVal(h);
h->cstr.pCounterVal = 0;
if (CIDFONT)
h->type1.cid.charDataCount = 0;
}
static void InitCharstr(XCF_Handle h)
{
h->cstr.pen = PenNull;
h->cstr.hints = InitialHints;
h->cstr.waitingForHsbw = true;
h->cstr.waitingForFirstHint = true;
h->cstr.stackTop = 0;
h->cstr.hintCount = 0;
h->cstr.counterGroupCount = 0;
h->cstr.counterGroupVCount = 0;
h->cstr.counterGroupHCount = 0;
IntToPSV(h->cstr.x, 0);
IntToPSV(h->cstr.y, 0);
h->cstr.subrFlatten = h->options.subrFlatten;
/* Initialize the seac characters */
h->cstr.baseSeac = 0;
h->cstr.accentSeac = 0;
}
void XC_ProcessCharstr(XCF_Handle h)
{
boolean endCharFound = false;
InitCharstr(h);
if (!CIDFONT && h->options.subrFlatten)
FreeT1CharStr(h);
else
NewT1CharStr(h);
#ifdef T13
if (h->dict.fontType == 13)
XT13_ProcessCharstr(h, 0, &endCharFound, false);
else
#endif
if ((h->options.outputCharstrType != 2) && (h->dict.fontType != 1))
ProcessCharstr(h, 0, &endCharFound, false);
}
void XC_CleanUp(XCF_Handle h)
{
if (!CIDFONT)
{
NewT1Subr(h);
NewT1CharStr(h);
}
}
void CheckSeacCharString(XCF_Handle h, CardX index)
{
Card8 PTR_PREFIX *argList;
IntX argCount;
XCF_LookUpTableEntry(h, &h->fontSet.charStrings, index);
h->cstr.pen = PenNull;
h->cstr.hints = InitialHints;
h->cstr.waitingForHsbw = true;
h->cstr.waitingForFirstHint = true;
h->cstr.stackTop = 0;
h->cstr.hintCount = 0;
h->cstr.counterGroupCount = 0;
h->cstr.counterGroupVCount = 0;
h->cstr.counterGroupHCount = 0;
IntToPSV(h->cstr.x, 0);
IntToPSV(h->cstr.y, 0);
h->cstr.baseSeac = 0;
h->cstr.accentSeac = 0;
h->cstr.stackTop = 0;
argList = h->inBuffer.pos;
argCount = XCF_FindNextOperator(h, &h->cstr.opCode, false);
if ((h->cstr.stackTop + argCount) > MAX_OPERAND_STACK)
XCF_FATAL_ERROR(h, XCF_StackOverflow, "Charstring Stack Overflow", h->cstr.stackTop + argCount );
CopyArgumentsToStack(h, argList, argCount, (h->cstr.opCode == t2_blend));
if (h->cstr.opCode == tx_endchar && h->cstr.stackTop >= 4)
{
h->cstr.baseSeac = FIXED_TO_INT(h->cstr.stack[2]->value[0]);
h->cstr.accentSeac = FIXED_TO_INT(h->cstr.stack[3]->value[0]);
}
}
/* All charstring stack operations are performed using the fixed point type.
The following functions deal with storing and retrieving values from
the stack. */
/* Push fixed point number on stack (as fixed) */
static void PushFix(XCF_Handle h, Fixed f)
{
if (h->cstr.stackTop >= MAX_OPERAND_STACK)
XCF_FATAL_ERROR(h, XCF_StackOverflow, "Charstring Stack Overflow",
h->cstr.stackTop);
h->cstr.stack[h->cstr.stackTop]->value[0] = f;
h->cstr.stack[h->cstr.stackTop++]->blend = false;
}
/* Push integer number on stack (as fixed) */
static void PushInt(XCF_Handle h, long l)
{
if (h->cstr.stackTop >= MAX_OPERAND_STACK)
XCF_FATAL_ERROR(h, XCF_StackOverflow, "Charstring Stack Overflow",
h->cstr.stackTop);
h->cstr.stack[h->cstr.stackTop]->value[0] = INT_TO_FIXED(l);
h->cstr.stack[h->cstr.stackTop++]->blend = false;
}
/* Pop number from stack (return fixed) */
static Fixed PopFix(XCF_Handle h)
{
if (h->cstr.stackTop < 1)
XCF_FATAL_ERROR(h, XCF_StackUnderflow, "Charstring Stack Underflow",
h->cstr.stackTop);
h->cstr.stackTop -= 1;
return h->cstr.stack[h->cstr.stackTop]->value[0];
}
/* Pop number from stack (return long) */
static long PopInt(XCF_Handle h)
{
if (h->cstr.stackTop < 1)
XCF_FATAL_ERROR(h, XCF_StackUnderflow, "Charstring Stack Underflow",
h->cstr.stackTop);
h->cstr.stackTop -= 1;
return (FIXED_TO_INT(h->cstr.stack[h->cstr.stackTop]->value[0]));
}
/* Select registry item. */
static Fixed *SelRegItem(XCF_Handle h, int reg, int *regSize)
{
switch (reg)
{
case TX_REG_WV:
*regSize = TX_MAX_MASTERS;
return h->dict.weightVector;
case TX_REG_NDV:
*regSize = TX_MAX_AXES;
return h->dict.normDesignVector;
case TX_REG_UDV:
*regSize = TX_MAX_AXES;
return h->dict.userDesignVector;
default:
XCF_FATAL_ERROR(h, XCF_InternalError, "unknown registry item", reg);
}
return 0; /* Suppress compiler warning */
}
/* Parse and execute the given charstring. This is used specifically for
multiple master fonts when converting a user design vector to a
weight vector. It can be used more generally when functionality is
added for more operators. */
int XC_ParseCharStr(XCF_Handle h, unsigned char PTR_PREFIX *cstr, int init)
{
int i;
Fixed PTR_PREFIX *bcArray = NULL;
if (!h->callbacks.allocate((void PTR_PREFIX * PTR_PREFIX *)&bcArray,
h->dict.lenBuildCharArray * sizeof(Fixed), h->callbacks.allocateHook))
XCF_FATAL_ERROR(h, XCF_MemoryAllocationError,
"Failure to allocate memory for buildchar array", h->dict.lenBuildCharArray);
switch (init)
{
case 1:
break;
case 2:
InitCharstr(h);
break;
}
i = 0;
for (;;)
switch (cstr[i])
{
case tx_endchar:
if (bcArray != NULL)
h->callbacks.allocate((void PTR_PREFIX * PTR_PREFIX *)&bcArray, 0,
h->callbacks.allocateHook);
return i + 1; /* Return charstring length */
case tx_reserved0:
case t2_reserved2:
case t2_reserved9:
case t2_reserved13:
case t2_reserved15:
case t2_reserved17:
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Reserved Charstring Operator",
cstr[i]);
case tx_rlineto:
case tx_hlineto:
case tx_vlineto:
case tx_rrcurveto:
case tx_callsubr:
case tx_return:
case t2_rcurveline:
case t2_rlinecurve:
case t2_vvcurveto:
case t2_hhcurveto:
case t2_callgsubr:
case tx_vhcurveto:
case tx_hvcurveto:
case tx_rmoveto:
case tx_hmoveto:
case tx_vmoveto:
case tx_hstem:
case tx_vstem:
case t2_hstemhm:
case t2_vstemhm:
case t2_hintmask:
case t2_cntrmask:
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Unsupported Charstring Operator", cstr[i]);
break;
case tx_escape:
{
Fixed a;
Fixed b;
Fixed x;
Fixed y;
switch (cff_ESC(cstr[i + 1]))
{
case tx_dotsection:
break;
default:
case t2_reservedESC1:
case t2_reservedESC2:
case t2_reservedESC6:
case t2_reservedESC7:
case t2_reservedESC16:
case t2_reservedESC17:
case tx_reservedESC25:
case tx_reservedESC31:
case tx_reservedESC32:
case t2_reservedESC33:
case t2_reservedESC19:
case t2_cntron:
XCF_FATAL_ERROR(h, XCF_InvalidCharString,
"Reserved Charstring Operator", cstr[i+1]);
case tx_and:
b = PopFix(h);
a = PopFix(h);
PushInt(h, a || b);
break;
case tx_not:
a = PopFix(h);
PushInt(h, !a);
break;
case tx_store:
{
Int32 count = PopInt(h);
Int32 i = PopInt(h);
Int32 j = PopInt(h);
Int32 iReg = PopInt(h);
int regSize;
Fixed *reg = SelRegItem(h, (int)iReg, &regSize);
if (i < 0 || i + count - 1 >= h->dict.lenBuildCharArray ||
j < 0 || j + count - 1 >= regSize)
XCF_FATAL_ERROR(h, XCF_IndexOutOfRange, "bounds check (store)", 0);
h->callbacks.memcpy(&reg[j], &bcArray[i], (unsigned short int)(sizeof(Fixed) * count));
}
break;
case tx_abs:
a = PopFix(h);
PushFix(h, (a < 0) ? -a : a);
break;
case tx_add:
b = PopFix(h);
a = PopFix(h);
PushFix(h, a + b);
break;
case tx_sub:
b = PopFix(h);
a = PopFix(h);
PushFix(h, a - b);
break;
case tx_div:
y = PopFix(h);
x = PopFix(h);
if (y == 0)
XCF_FATAL_ERROR(h, XCF_InvalidNumber, "divide by zero (div)", 0);
PushFix(h, XCF_FixDiv(x, y));
break;
case tx_load:
{
int regSize;
Int32 count = PopInt(h);
Int32 i = PopInt(h);
Int32 iReg = PopInt(h);
Fixed *reg = SelRegItem(h, (int)iReg, &regSize);
if (i < 0 || i + count - 1 >= h->dict.lenBuildCharArray || count >
regSize)
XCF_FATAL_ERROR(h, XCF_IndexOutOfRange, "bounds check (load)", i);
h->callbacks.memcpy(&bcArray[i], &reg[0], (unsigned short int)(sizeof(Fixed) * count));
}
break;
case tx_neg:
a = PopFix(h);
PushFix(h, -a);
break;
case tx_eq:
b = PopFix(h);
a = PopFix(h);
PushInt(h, a == b);
break;
case tx_drop:
(void)PopFix(h);
break;
case tx_put:
{
Int32 i = PopInt(h);
if (i < 0 || i >= h->dict.lenBuildCharArray)
XCF_FATAL_ERROR(h, XCF_IndexOutOfRange, "bounds check (put)", i);
bcArray[i] = PopFix(h);
}
break;
case tx_get:
{
Int32 i = PopInt(h);
if (i < 0 || i >= h->dict.lenBuildCharArray)
XCF_FATAL_ERROR(h, XCF_IndexOutOfRange, "bounds check (get)", i);
PushFix(h, bcArray[i]);
}
break;
case tx_ifelse:
{
Fixed v2 = PopFix(h);
Fixed v1 = PopFix(h);
Fixed s2 = PopFix(h);
Fixed s1 = PopFix(h);
PushFix(h, (v1 > v2) ? s2 : s1);
}
break;
case tx_random:
/* For generators that aren't very random in the low order bits
(a common problem) the following is a good example of what
not to do. However, obtaining good randomness is not very
important in this application so I opted for simplicity */
/* PushFix(h, rand() % FIXEDONE + 1); */
break;
case tx_mul:
y = PopFix(h);
x = PopFix(h);
PushFix(h, XCF_FixMul(x, y));
break;
case tx_dup:
PushFix(h, h->cstr.stack[h->cstr.stackTop - 1]->value[0]);
break;
case tx_exch:
b = PopFix(h);
a = PopFix(h);
PushFix(h, b);
PushFix(h, a);
break;
case tx_index:
{
Int32 i = PopInt(h);
if (i < 0)
i = 0; /* Duplicate top element */
if (i >= (int)h->cstr.stackTop)
XCF_FATAL_ERROR(h, XCF_IndexOutOfRange, "limit check (index)", i);
PushFix(h, h->cstr.stack[h->cstr.stackTop - 1 - i]->value[0]);
}
break;
case tx_roll:
{
int k;
int iSrc;
int iDst;
Fixed tmp[T2_MAX_OP_STACK];
int tmpSize = sizeof(tmp) / sizeof(Fixed);
Int32 j = PopInt(h);
Int32 n = PopInt(h);
int iBottom = h->cstr.stackTop - (int)n;
if (n < 0 || iBottom < 0)
XCF_FATAL_ERROR(h, XCF_IndexOutOfRange, "limit check (roll)", 0);
if (j < 0)
j += n; /* Convert to positive roll */
j %= n; /* Constrain j to (-n,n) */
if (j < 0)
j += n; /* Constrain j to [0,n) */
iSrc = iBottom;
iDst = iBottom + (int)j;
for (k = 0; (Int32)k < n - j; k++)
{
if (iDst >= tmpSize)
break;
tmp[iDst++] = h->cstr.stack[iSrc++]->value[0];
}
iSrc = iBottom + (int)n - (int)j;
iDst = iBottom;
for (k = 0; k < j; k++)
{
if (iDst >= tmpSize)
break;
tmp[iDst++] = h->cstr.stack[iSrc++]->value[0];
}
for (k = iBottom; k < (int)h->cstr.stackTop; k++)
{
if (k >= tmpSize)
break;
h->cstr.stack[k]->value[0] = tmp[k];
}
}
break;
case t2_hflex:
case t2_flex:
case t2_hflex1:
case t2_flex1:
case tx_sqrt:
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Unsupported Charstring Operator", cstr[i]);
break;
}
i += 2;
}
break;
case t2_blend:
/* Blend(h); */
i++;
break;
case t2_shortint:
PushInt(h, cstr[i + 1]<<8 | cstr[i + 2]);
i += 3;
break;
case 247: case 248: case 249: case 250:
/* Positive 2 byte number */
PushInt(h, 108 + 256 * (cstr[i] - 247) + cstr[i + 1]);
i += 2;
break;
case 251: case 252: case 253: case 254:
/* Negative 2 byte number */
PushInt(h, -108 - 256 * (cstr[i] - 251) - cstr[i + 1]);
i += 2;
break;
case 255:
/* 5 byte number */
PushFix(h, (long)cstr[i + 1]<<24 | (long)cstr[i + 2]<<16 |
cstr[i + 3]<<8 | cstr[i + 4]);
i += 5;
break;
default:
/* 1 byte number */
PushInt(h, cstr[i] - 139);
i++;
break;
}
}
/* Read the charstring and include as a subroutine. */
static int CharStrToSubr(XCF_Handle h, unsigned char PTR_PREFIX *cstr)
{
int i;
int j;
Card16 op;
NewT1Subr(h);
h->cstr.stackTop = 0;
i = 0;
for (;;)
switch (cstr[i])
{
case tx_endchar:
XC_WriteT1OpCode(h, tx_endchar, true);
return i + 1; /* Return charstring length */
case tx_reserved0:
case t2_reserved2:
case t2_reserved9:
case t2_reserved13:
case t2_reserved15:
case t2_reserved17:
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Reserved Charstring Operator",
cstr[i]);
case tx_rlineto:
case tx_hlineto:
case tx_vlineto:
case tx_rrcurveto:
case tx_callsubr:
case tx_return:
case t2_rcurveline:
case t2_rlinecurve:
case t2_vvcurveto:
case t2_hhcurveto:
case t2_callgsubr:
case tx_vhcurveto:
case tx_hvcurveto:
case tx_rmoveto:
case tx_hmoveto:
case tx_vmoveto:
case tx_hstem:
case tx_vstem:
case t2_hstemhm:
case t2_vstemhm:
case t2_hintmask:
case t2_cntrmask:
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Unsupported Charstring Operator in Design Vector subr", cstr[i]);
break;
case tx_escape:
{
switch (cff_ESC(cstr[i + 1]))
{
case tx_dotsection:
break;
default:
case t2_reservedESC1:
case t2_reservedESC2:
case t2_reservedESC6:
case t2_reservedESC7:
case t2_reservedESC16:
case t2_reservedESC17:
case tx_reservedESC25:
case tx_reservedESC31:
case tx_reservedESC32:
case t2_reservedESC33:
case t2_reservedESC19:
case t2_cntron:
XCF_FATAL_ERROR(h, XCF_InvalidCharString,
"Reserved Charstring Operator", cstr[i+1]);
case tx_and:
case tx_not:
case tx_store:
case tx_abs:
case tx_add:
case tx_sub:
case tx_div:
case tx_load:
case tx_neg:
case tx_eq:
case tx_drop:
case tx_put:
case tx_get:
case tx_ifelse:
case tx_random:
case tx_mul:
case tx_dup:
case tx_exch:
case tx_index:
case tx_roll:
for (j = 0; j < (int)h->cstr.stackTop; j++)
XC_WriteT1PStackValue(h, h->cstr.stack[j], true);
op = (cstr[i] << 8) | cstr[i+1];
XC_WriteT1OpCode(h, op, true);
h->cstr.stackTop = 0;
break;
case t2_hflex:
case t2_flex:
case t2_hflex1:
case t2_flex1:
case tx_sqrt:
XCF_FATAL_ERROR(h, XCF_InvalidCharString, "Unsupported Charstring Operator", cstr[i]);
break;
}
i += 2;
}
break;
case t2_blend:
/* Blend(h); */
i++;
break;
case t2_shortint:
PushInt(h, cstr[i + 1]<<8 | cstr[i + 2]);
i += 3;
break;
case 247: case 248: case 249: case 250:
/* Positive 2 byte number */
PushInt(h, 108 + 256 * (cstr[i] - 247) + cstr[i + 1]);
i += 2;
break;
case 251: case 252: case 253: case 254:
/* Negative 2 byte number */
PushInt(h, -108 - 256 * (cstr[i] - 251) - cstr[i + 1]);
i += 2;
break;
case 255:
/* 5 byte number */
PushFix(h, (long)cstr[i + 1]<<24 | (long)cstr[i + 2]<<16 |
cstr[i + 3]<<8 | cstr[i + 4]);
i += 5;
break;
default:
/* 1 byte number */
PushInt(h, cstr[i] - 139);
i++;
break;
}
}
/* Write out NDV and CDV as subroutines. */
void XC_DVToSubr(XCF_Handle h)
{
char PTR_PREFIX *str;
Card16 length;
XCF_LookUpString(h, h->dict.ndv, &str, &length);
CharStrToSubr(h, (unsigned char PTR_PREFIX *)str);
XCF_LookUpString(h, h->dict.cdv, &str, &length);
CharStrToSubr(h, (unsigned char PTR_PREFIX *)str);
NewT1Subr(h);
}
#if HAS_COOLTYPE_UFL == 1
/* Returns 1 if i is a character with transitional designs and has
already been processed. */
int XC_TransDesignChar(XCF_Handle h, CardX sid)
{
/* JimboMM transitional characters */
static unsigned char Jimbo0_cstr[] =
{
#include "xcf_jimbo0.h"
};
static unsigned char Jimbo1_cstr[] =
{
#include "xcf_jimbo1.h"
};
static unsigned char Jimbo2_cstr[] =
{
#include "xcf_jimbo2.h"
};
static TransChar Jimbo_chars[] =
{
{50, {sizeof(Jimbo0_cstr), (char *)Jimbo0_cstr}},
{56, {sizeof(Jimbo1_cstr), (char *)Jimbo1_cstr}},
{88, {sizeof(Jimbo2_cstr), (char *)Jimbo2_cstr}},
};
/* ITCGaramond Roman transitional characters */
static unsigned char GaraRm0_cstr[] =
{
#include "xcf_rgara0.h"
};
static unsigned char GaraRm1_cstr[] =
{
#include "xcf_rgara1.h"
};
static unsigned char GaraRm2_cstr[] =
{
#include "xcf_rgara2.h"
};
static unsigned char GaraRm3_cstr[] =
{
#include "xcf_rgara3.h"
};
static TransChar GaraRm_chars[] =
{
{56, {sizeof(GaraRm0_cstr), (char *)GaraRm0_cstr}},
{97, {sizeof(GaraRm1_cstr), (char *)GaraRm1_cstr}},
{ 5, {sizeof(GaraRm2_cstr), (char *)GaraRm2_cstr}},
{88, {sizeof(GaraRm3_cstr), (char *)GaraRm3_cstr}},
};
/* ITCGaramond Italic transitional characters */
static unsigned char GaraIt0_cstr[] =
{
#include "xcf_igara0.h"
};
static unsigned char GaraIt1_cstr[] =
{
#include "xcf_igara1.h"
};
static unsigned char GaraIt2_cstr[] =
{
#include "xcf_igara2.h"
};
static unsigned char GaraIt3_cstr[] =
{
#include "xcf_igara3.h"
};
static unsigned char GaraIt4_cstr[] =
{
#include "xcf_igara4.h"
};
static TransChar GaraIt_chars[] =
{
{ 56, {sizeof(GaraIt0_cstr), (char *)GaraIt0_cstr}},
{ 97, {sizeof(GaraIt1_cstr), (char *)GaraIt1_cstr}},
{ 5, {sizeof(GaraIt2_cstr), (char *)GaraIt2_cstr}},
{ 32, {sizeof(GaraIt3_cstr), (char *)GaraIt3_cstr}},
{123, {sizeof(GaraIt4_cstr), (char *)GaraIt4_cstr}},
};
char fontName[512];
TransChar *transCharTbl = 0;
Card16 tblLen = 0;
Card16 i, j;
if (XCF_FontName(h, (unsigned short int)h->fontSet.fontIndex, fontName,
(unsigned short int)512) != XCF_Ok)
return 0;
if (h->callbacks.strcmp(fontName, "ITCGaramondMM") == 0)
{
transCharTbl = GaraRm_chars;
tblLen = sizeof(GaraRm_chars)/sizeof(GaraRm_chars[0]);
}
else if (h->callbacks.strcmp(fontName, "ITCGaramondMM-It") == 0)
{
transCharTbl = GaraIt_chars;
tblLen = sizeof(GaraIt_chars)/sizeof(GaraIt_chars[0]);
}
else if (h->callbacks.strcmp(fontName, "JimboMM") == 0)
{
transCharTbl = Jimbo_chars;
tblLen = sizeof(Jimbo_chars)/sizeof(Jimbo_chars[0]);
}
if (tblLen == 0) /* Not a font with transitional designs. */
return 0;
for (i = 0; i < tblLen; i++)
if (transCharTbl[i].sid == sid)
{
Card8 PTR_PREFIX *args;
IntX argCount;
InitCharstr(h);
if (h->options.subrFlatten)
FreeT1CharStr(h);
else
NewT1CharStr(h);
h->inBuffer.pos = (Card8 *)transCharTbl[i].cstr.cstr;
h->inBuffer.blockLength = transCharTbl[i].cstr.length;
h->inBuffer.end = h->inBuffer.pos + h->inBuffer.blockLength;
while (h->inBuffer.pos < h->inBuffer.end)
{
args = h->inBuffer.pos;
argCount = XCF_FindNextOperator(h, &h->cstr.opCode, false);
if ((h->cstr.stackTop + argCount) > MAX_OPERAND_STACK)
XCF_FATAL_ERROR(h, XCF_StackOverflow, "Charstring Stack Overflow", h->cstr.stackTop + argCount );
CopyArgumentsToStack(h, args, argCount, (h->cstr.opCode == t2_blend));
for (j = 0; j < h->cstr.stackTop; j++)
XC_WriteT1PStackValue(h, h->cstr.stack[j], false);
XC_WriteT1OpCode(h, h->cstr.opCode, false);
h->cstr.stackTop = 0;
}
return 1;
}
return 0;
}
/* Only processes the subroutines associated with transitional
design characters. */
void XC_ProcessTransDesignSubrs(XCF_Handle h)
{
Card16 i;
char fontName[512];
Card16 tblLen = 0;
short *subrTbl = 0;
boolean endCharFound = false;
static short Jimbo_subrs[] = {0, 1, 2, 3, 4, 5};
static short GaraRm_subrs[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
static short GaraIt_subrs[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
if (XCF_FontName(h, (unsigned short int)h->fontSet.fontIndex, fontName,
(unsigned short int)512) != XCF_Ok)
return;
if (h->callbacks.strcmp(fontName, "ITCGaramondMM") == 0)
{
subrTbl = GaraRm_subrs;
tblLen = sizeof(GaraRm_subrs)/sizeof(GaraRm_subrs[0]);
}
else if (h->callbacks.strcmp(fontName, "ITCGaramondMM-It") == 0)
{
subrTbl = GaraIt_subrs;
tblLen = sizeof(GaraIt_subrs)/sizeof(GaraIt_subrs[0]);
}
else if (h->callbacks.strcmp(fontName, "JimboMM") == 0)
{
subrTbl = Jimbo_subrs;
tblLen = sizeof(Jimbo_subrs)/sizeof(Jimbo_subrs[0]);
}
if (tblLen == 0) /* Not a font with transitional designs. */
return;
for (i = 0; i < tblLen; i++)
{
InitCharstr(h);
NewT1Subr(h);
XCF_LookUpTableEntry(h, &h->dict.localSubrs, subrTbl[i]);
#ifdef T13
if (h->dict.fontType == 13)
XT13_ProcessCharstr(h, 0, &endCharFound, true);
else
#endif
ProcessCharstr(h, 0, &endCharFound, true);
}
}
#endif
#ifdef __cplusplus
}
#endif