Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

5502 lines
136 KiB

/*********************************************************************
interp.c -- TT Rasterizer Interpreter Module
Copyright: (c) 1987-1990, 1992 by Apple Computer, Inc., all rights reserved.
(c) 1989-1993. Microsoft Corporation, all rights reserved.
8/12/94 deanb 55 orphan routine CHECK_STATE deleted
2/09/94 deanb 54 RASTERIZER_VERSION defined for GETINFO
12/17/93 deanb 53 CHECK_POINT zone corrected in MIRP
12/08/93 deanb 52 itrp_SCANTYPE enabled for smart dropout control
9/15/93 deanb 51 InnerTraceEx double call fixed; iOpCode -> lOpCode
7/29/93 deanb 50 ALIGNPTS, SHE fixed; InnerTraceExecute saves first
7/12/93 deanb 49 itrp_IllegalInstruction works
6/28/93 deanb 48 gbyPushTable made const
2/16/93 deanb 47 fxUnRounded set after check single width
2/15/93 deanb 46 fall back to MIRPG when using single width
2/15/93 deanb 45 vector defaults for FONTPROGRAM, stat back
2/12/93 deanb 44 delete stat code
2/12/93 deanb 43 cleanup MSIRP & itrp_Execute
2/12/93 deanb 42 branch itrp_IP on MovePoint
2/11/93 deanb 41 use c8 register calling convetions
2/11/93 deanb 40 switch to Microsoft C ver 8
2/09/93 deanb 39 skipPushData inline in itrp_IF
2/09/93 deanb 38 do fast MIRP's with if statments
2/09/93 deanb 37 remove fast MDRPX and MIRPY routines
2/09/93 deanb 36 fast MDRPX and MIRPY routines
2/08/93 deanb 35 cleanup MIRPs, combine if statments
2/08/93 deanb 34 dual rounding with 6 ptr init values
2/08/93 deanb 33 IUP inner loop pointer check
2/08/93 deanb 32 repair skipPushData for npushw
2/05/93 deanb 31 check for fxHintedDelta = 0
2/05/93 deanb 30 use roundFuncPtr in fast MIRP's
2/05/93 deanb 29 itrp_SWAP done in place
2/05/93 deanb 28 fntMirpFunc defined for MIRPG/X/Y
2/05/93 deanb 27 iOpCode passed in to all functions
2/05/93 deanb 26 use instr ptr for param and return
2/04/93 deanb 25 pull oldRange out of itrp_IP loops
2/04/93 deanb 24 movePoint check for proj.x/y = 1
2/03/93 deanb 23 table driven skipPushData
2/03/93 deanb 22 zero based Unary Operand pointers
2/01/93 deanb 21 split out SetRoundState
2/01/93 deanb 20 eliminate OpCode assignemnt, registers
2/01/93 deanb 19 bump Normalize limit up to 0x20000000L
1/29/93 deanb 18 add SuperRound MIRPG fallback
1/29/93 deanb 17 fast MIRPX and MIRPY routines
1/27/93 deanb 16 single rounding routines restored
1/27/93 deanb 15 innerExecute tune up
1/27/93 deanb 14 rounding routines for engine/no engine
1/27/93 deanb 13 repair itrp_Normalize for BIG vectors
1/26/93 deanb 12 split out SPVTCA and SFVTCA
1/26/93 deanb 11 clean up itrp_IP
1/26/93 deanb 10 return IUP to old start/end calc
1/25/93 deanb 9 use pointers in IUP loops
1/25/93 deanb 8 major rewrite of itrp_IUP
1/25/93 deanb 7 rewrite itrp_Normalize
1/22/93 deanb 6 split and do Unary Operands in place
1/22/93 deanb 5 do Binary Operands in place
1/22/93 deanb 4 split out BinaryOperand
1/22/93 deanb 3 split out PUSHB1 and PUSHW1
1/22/93 deanb 2 split out PushSomeBytes/Words
1/22/93 deanb 1 split out SRP0-2, LLOOP, POP
1/22/93 deanb 0 STAT card timing added
1/22/93 deanb dead code/comments moved to history.fnt
**********************************************************************/
// added by bodind, speed optimization
#include "nt.h"
#include "ntrtl.h"
#include "fscdefs.h"
#include "fontmath.h"
#include "sfnt.h"
#include "fnt.h"
#include "interp.h"
#include "fserror.h"
#include "stat.h" /* for STAT card timing only */
#include <stdio.h>
#ifdef SEGMENT_LINK
#pragma segment FNT_C
#endif
/* perfect spot size (Fixed) */
#ifndef FIXEDSQRT2
#define FIXEDSQRT2 0x00016A0A
#endif
#define RASTERIZER_VERSION 34 /* MS reserved values 33 - 64 */
/* 33 = Rasterizer v1.5 */
/* 34 = Rasterizer v1.6 */
#define MAX_ELEMENTS 2
#define TWILIGHTZONE 0 /* The point storage */
#define GLYPHELEMENT 1 /* The actual glyph */
#define MAXANGLES 20
#define ROTATEDGLYPH 0x100
#define STRETCHEDGLYPH 0x200
#define MAXBYTE_INSTRUCTIONS 256
#define ONEVECTOR ONESHORTFRAC
#define VECTORMUL(value, component) ShortFracMul((F26Dot6)(value), (ShortFract)(component))
#define VECTORDOT(a,b) ShortFracDot((ShortFract)(a),(ShortFract)(b))
#define VECTORDIV(num,denum) ShortFracDiv((ShortFract)(num),(ShortFract)(denum))
#define VECTORMULDIV(a,b,c) ShortFracMulDiv((ShortFract)(a),(ShortFract)(b),(ShortFract)(c))
#define VECTOR2FIX(a) ((Fixed) (a) << 2)
#define ONESIXTEENTHVECTOR ((ONEVECTOR) >> 4)
#ifdef FSCFG_REENTRANT
#define GSP0 fnt_LocalGraphicStateType* pLocalGS
#define GSP fnt_LocalGraphicStateType* pLocalGS,
#define GSA0 pLocalGS
#define GSA pLocalGS,
#define LocalGS (*pLocalGS)
#else
#define GSP0 void
#define GSP
#define GSA0
#define GSA
fnt_LocalGraphicStateType LocalGS
#ifndef FSCFG_NO_INITIALIZED_DATA
= {0}
#endif
;
#endif
/* Common Interpreter Function Parameter */
#define IPARAM GSP uint8 *pbyInst, int32 lOpCode
#define MIRPG 0
#define MIRPX 1
#define MIRPY 2
/* Private function prototypes */
FS_PRIVATE F26Dot6 itrp_RoundToDoubleGrid(GSP F26Dot6 xin, F26Dot6 engine);
FS_PRIVATE F26Dot6 itrp_RoundDownToGrid(GSP F26Dot6 xin, F26Dot6 engine);
FS_PRIVATE F26Dot6 itrp_RoundUpToGrid(GSP F26Dot6 xin, F26Dot6 engine);
FS_PRIVATE F26Dot6 itrp_RoundToGrid(GSP F26Dot6 xin, F26Dot6 engine);
FS_PRIVATE F26Dot6 itrp_RoundToHalfGrid(GSP F26Dot6 xin, F26Dot6 engine);
FS_PRIVATE F26Dot6 itrp_RoundOff(GSP F26Dot6 xin, F26Dot6 engine);
FS_PRIVATE F26Dot6 itrp_SuperRound(GSP F26Dot6 xin, F26Dot6 engine);
FS_PRIVATE F26Dot6 itrp_Super45Round(GSP F26Dot6 xin, F26Dot6 engine);
FS_PRIVATE void itrp_Normalize (F26Dot6 x, F26Dot6 y, VECTOR* pVec);
FS_PRIVATE void itrp_MovePoint (GSP fnt_ElementType *element, int32 point, F26Dot6 delta);
FS_PRIVATE void itrp_XMovePoint (GSP fnt_ElementType *element, int32 point, F26Dot6 delta);
FS_PRIVATE void itrp_YMovePoint (GSP fnt_ElementType *element, int32 point, F26Dot6 delta);
FS_PRIVATE F26Dot6 itrp_Project (GSP F26Dot6 x, F26Dot6 y);
FS_PRIVATE F26Dot6 itrp_OldProject (GSP F26Dot6 x, F26Dot6 y);
FS_PRIVATE F26Dot6 itrp_XProject (GSP F26Dot6 x, F26Dot6 y);
FS_PRIVATE F26Dot6 itrp_YProject (GSP F26Dot6 x, F26Dot6 y);
FS_PRIVATE Fixed itrp_GetCVTScale (GSP0);
FS_PRIVATE F26Dot6 itrp_GetCVTEntryFast (GSP int32 n);
FS_PRIVATE F26Dot6 itrp_GetCVTEntrySlow (GSP int32 n);
FS_PRIVATE F26Dot6 itrp_GetSingleWidthFast (GSP0);
FS_PRIVATE F26Dot6 itrp_GetSingleWidthSlow (GSP0);
FS_PRIVATE void itrp_ChangeCvtFast (GSP fnt_ElementType *element, int32 number, F26Dot6 delta);
FS_PRIVATE void itrp_ChangeCvtSlow (GSP fnt_ElementType *element, int32 number, F26Dot6 delta);
FS_PRIVATE void itrp_InnerTraceExecute (GSP uint8 *ptr, uint8 *eptr);
FS_PRIVATE void itrp_InnerExecute (GSP uint8 *ptr, uint8 *eptr);
FS_PRIVATE void itrp_Check_PF_Proj (GSP0);
FS_PRIVATE void itrp_ComputeAndCheck_PF_Proj (GSP0);
FS_PRIVATE void itrp_SetRoundValues (GSP int32 arg1, int32 normalRound);
FS_PRIVATE F26Dot6 itrp_CheckSingleWidth (GSP F26Dot6 value);
FS_PRIVATE fnt_instrDef*itrp_FindIDef (GSP uint8 opCode);
FS_PRIVATE void itrp_DeltaEngine (GSP FntMoveFunc doIt, int16 base, int16 shift);
/* Actual instructions for the jump table */
FS_PRIVATE uint8* itrp_SVTCA_0 (IPARAM);
FS_PRIVATE uint8* itrp_SVTCA_1 (IPARAM);
FS_PRIVATE uint8* itrp_SPVTCA_0 (IPARAM);
FS_PRIVATE uint8* itrp_SPVTCA_1 (IPARAM);
FS_PRIVATE uint8* itrp_SFVTCA_0 (IPARAM);
FS_PRIVATE uint8* itrp_SFVTCA_1 (IPARAM);
FS_PRIVATE uint8* itrp_SPVTL (IPARAM);
FS_PRIVATE uint8* itrp_SDPVTL (IPARAM);
FS_PRIVATE uint8* itrp_SFVTL (IPARAM);
FS_PRIVATE uint8* itrp_WPV (IPARAM);
FS_PRIVATE uint8* itrp_WFV (IPARAM);
FS_PRIVATE uint8* itrp_RPV (IPARAM);
FS_PRIVATE uint8* itrp_RFV (IPARAM);
FS_PRIVATE uint8* itrp_SFVTPV (IPARAM);
FS_PRIVATE uint8* itrp_ISECT (IPARAM);
FS_PRIVATE uint8* itrp_SRP0 (IPARAM);
FS_PRIVATE uint8* itrp_SRP1 (IPARAM);
FS_PRIVATE uint8* itrp_SRP2 (IPARAM);
FS_PRIVATE uint8* itrp_SetElementPtr (IPARAM);
FS_PRIVATE uint8* itrp_LLOOP (IPARAM);
FS_PRIVATE uint8* itrp_RTG (IPARAM);
FS_PRIVATE uint8* itrp_RTHG (IPARAM);
FS_PRIVATE uint8* itrp_RTDG (IPARAM);
FS_PRIVATE uint8* itrp_ROFF (IPARAM);
FS_PRIVATE uint8* itrp_RUTG (IPARAM);
FS_PRIVATE uint8* itrp_RDTG (IPARAM);
FS_PRIVATE uint8* itrp_SROUND (IPARAM);
FS_PRIVATE uint8* itrp_S45ROUND (IPARAM);
FS_PRIVATE uint8* itrp_LMD (IPARAM);
FS_PRIVATE uint8* itrp_RAW (IPARAM);
FS_PRIVATE uint8* itrp_LWTCI (IPARAM);
FS_PRIVATE uint8* itrp_LSWCI (IPARAM);
FS_PRIVATE uint8* itrp_LSW (IPARAM);
FS_PRIVATE uint8* itrp_DUP (IPARAM);
FS_PRIVATE uint8* itrp_POP (IPARAM);
FS_PRIVATE uint8* itrp_CLEAR (IPARAM);
FS_PRIVATE uint8* itrp_SWAP (IPARAM);
FS_PRIVATE uint8* itrp_DEPTH (IPARAM);
FS_PRIVATE uint8* itrp_CINDEX (IPARAM);
FS_PRIVATE uint8* itrp_MINDEX (IPARAM);
FS_PRIVATE uint8* itrp_ROTATE (IPARAM);
FS_PRIVATE uint8* itrp_MDAP (IPARAM);
FS_PRIVATE uint8* itrp_MIAP (IPARAM);
FS_PRIVATE uint8* itrp_IUP (IPARAM);
FS_PRIVATE uint8* itrp_SHP (IPARAM);
FS_PRIVATE uint8* itrp_SHC (IPARAM);
FS_PRIVATE uint8* itrp_SHE (IPARAM);
FS_PRIVATE uint8* itrp_SHPIX (IPARAM);
FS_PRIVATE uint8* itrp_IP (IPARAM);
FS_PRIVATE uint8* itrp_MSIRP (IPARAM);
FS_PRIVATE uint8* itrp_ALIGNRP (IPARAM);
FS_PRIVATE uint8* itrp_ALIGNPTS (IPARAM);
FS_PRIVATE uint8* itrp_SANGW (IPARAM);
FS_PRIVATE uint8* itrp_FLIPPT (IPARAM);
FS_PRIVATE uint8* itrp_FLIPRGON (IPARAM);
FS_PRIVATE uint8* itrp_FLIPRGOFF (IPARAM);
FS_PRIVATE uint8* itrp_SCANCTRL (IPARAM);
FS_PRIVATE uint8* itrp_SCANTYPE (IPARAM);
FS_PRIVATE uint8* itrp_INSTCTRL (IPARAM);
FS_PRIVATE uint8* itrp_AA (IPARAM);
FS_PRIVATE uint8* itrp_NPUSHB (IPARAM);
FS_PRIVATE uint8* itrp_NPUSHW (IPARAM);
FS_PRIVATE uint8* itrp_WS (IPARAM);
FS_PRIVATE uint8* itrp_RS (IPARAM);
FS_PRIVATE uint8* itrp_WCVT (IPARAM);
FS_PRIVATE uint8* itrp_WCVTFOD (IPARAM);
FS_PRIVATE uint8* itrp_RCVT (IPARAM);
FS_PRIVATE uint8* itrp_RC (IPARAM);
FS_PRIVATE uint8* itrp_WC (IPARAM);
FS_PRIVATE uint8* itrp_MD (IPARAM);
FS_PRIVATE uint8* itrp_MPPEM (IPARAM);
FS_PRIVATE uint8* itrp_MPS (IPARAM);
FS_PRIVATE uint8* itrp_GETINFO (IPARAM);
FS_PRIVATE uint8* itrp_FLIPON (IPARAM);
FS_PRIVATE uint8* itrp_FLIPOFF (IPARAM);
FS_PRIVATE uint8* itrp_IF (IPARAM);
FS_PRIVATE uint8* itrp_ELSE (IPARAM);
FS_PRIVATE uint8* itrp_EIF (IPARAM);
FS_PRIVATE uint8* itrp_JMPR (IPARAM);
FS_PRIVATE uint8* itrp_JROT (IPARAM);
FS_PRIVATE uint8* itrp_JROF (IPARAM);
FS_PRIVATE uint8* itrp_ROUND (IPARAM);
FS_PRIVATE uint8* itrp_NROUND (IPARAM);
FS_PRIVATE uint8* itrp_PUSHB (IPARAM);
FS_PRIVATE uint8* itrp_PUSHW (IPARAM);
FS_PRIVATE uint8* itrp_MDRP (IPARAM);
FS_PRIVATE uint8* itrp_MIRP (IPARAM);
FS_PRIVATE uint8* itrp_CALL (IPARAM);
FS_PRIVATE uint8* itrp_FDEF (IPARAM);
FS_PRIVATE uint8* itrp_LOOPCALL (IPARAM);
FS_PRIVATE uint8* itrp_IDefPatch (IPARAM);
FS_PRIVATE uint8* itrp_IDEF (IPARAM);
FS_PRIVATE uint8* itrp_UTP (IPARAM);
FS_PRIVATE uint8* itrp_SDB (IPARAM);
FS_PRIVATE uint8* itrp_SDS (IPARAM);
FS_PRIVATE uint8* itrp_DELTAP1 (IPARAM);
FS_PRIVATE uint8* itrp_DELTAP2 (IPARAM);
FS_PRIVATE uint8* itrp_DELTAP3 (IPARAM);
FS_PRIVATE uint8* itrp_DELTAC1 (IPARAM);
FS_PRIVATE uint8* itrp_DELTAC2 (IPARAM);
FS_PRIVATE uint8* itrp_DELTAC3 (IPARAM);
FS_PRIVATE uint8* itrp_PUSHB1 (IPARAM);
FS_PRIVATE uint8* itrp_PUSHW1 (IPARAM);
FS_PRIVATE uint8* itrp_LT (IPARAM);
FS_PRIVATE uint8* itrp_LTEQ (IPARAM);
FS_PRIVATE uint8* itrp_GT (IPARAM);
FS_PRIVATE uint8* itrp_GTEQ (IPARAM);
FS_PRIVATE uint8* itrp_EQ (IPARAM);
FS_PRIVATE uint8* itrp_NEQ (IPARAM);
FS_PRIVATE uint8* itrp_AND (IPARAM);
FS_PRIVATE uint8* itrp_OR (IPARAM);
FS_PRIVATE uint8* itrp_ADD (IPARAM);
FS_PRIVATE uint8* itrp_SUB (IPARAM);
FS_PRIVATE uint8* itrp_DIV (IPARAM);
FS_PRIVATE uint8* itrp_MUL (IPARAM);
FS_PRIVATE uint8* itrp_MAX (IPARAM);
FS_PRIVATE uint8* itrp_MIN (IPARAM);
FS_PRIVATE uint8* itrp_ODD (IPARAM);
FS_PRIVATE uint8* itrp_EVEN (IPARAM);
FS_PRIVATE uint8* itrp_NOT (IPARAM);
FS_PRIVATE uint8* itrp_ABS (IPARAM);
FS_PRIVATE uint8* itrp_NEG (IPARAM);
FS_PRIVATE uint8* itrp_CEILING (IPARAM);
FS_PRIVATE uint8* itrp_FLOOR (IPARAM);
FS_PRIVATE uint8* itrp_IllegalInstruction (IPARAM);
FS_PRIVATE fnt_ElementType*itrp_SH_Common (GSP F26Dot6*dx, F26Dot6*dy, int32*point, int32 lOpCode);
FS_PRIVATE void itrp_SHP_Common (GSP F26Dot6 dx, F26Dot6 dy);
FS_PRIVATE uint8* itrp_PushSomeBytes (GSP int32, uint8*);
FS_PRIVATE uint8* itrp_PushSomeWords (GSP int32, uint8*);
FS_PRIVATE uint8* itrp_SkipPushData (GSP uint8*);
#ifndef NOT_ON_THE_MAC
#ifdef FSCFG_DEBUG
FS_PRIVATE void itrp_DDT (int8 c, int32 n);
#endif
#endif
FS_PRIVATE uint8* itrp_DEBUG (IPARAM);
FS_PRIVATE ErrorCode itrp_Execute (
fnt_ElementType * pTwilightElement,
fnt_ElementType * pGlyphElement,
uint8 * ptr,
uint8 * eptr,
fnt_GlobalGraphicStateType * globalGS,
FntTraceFunc TraceFunc);
/* GLOBAL GS INITIALIZATION */
FS_PUBLIC void itrp_UpdateGlobalGS(
void * pvGlobalGS, /* GlobalGS */
void * pvCVT, /* Pointer to control value table */
void * pvStore, /* Pointer to storage */
void * pvFuncDef, /* Pointer to function defintions */
void * pvInstrDef, /* Pointer to instruction definitions */
void * pvStack, /* Pointer to the stack */
LocalMaxProfile * maxp,
uint16 cvtCount,
uint32 ulLengthFontProgram, /* Length of font program */
void * pvFontProgram, /* Pointer to font program */
uint32 ulLengthPreProgram, /* Length of pre program */
void * pvPreProgram) /* Pointer to pre program */
{
fnt_GlobalGraphicStateType * globalGS;
globalGS = (fnt_GlobalGraphicStateType *)pvGlobalGS;
globalGS->controlValueTable = (F26Dot6 *)pvCVT;
globalGS->store = (F26Dot6 *)pvStore;
globalGS->funcDef = (fnt_funcDef *)pvFuncDef;
globalGS->instrDef = (fnt_instrDef *)pvInstrDef;
globalGS->stackBase = (F26Dot6 *)pvStack;
if(ulLengthFontProgram)
{
globalGS->pgmList[FONTPROGRAM].Length = ulLengthFontProgram;
globalGS->pgmList[FONTPROGRAM].Instruction = pvFontProgram;
}
else
{
globalGS->pgmList[FONTPROGRAM].Length = ulLengthFontProgram;
globalGS->pgmList[FONTPROGRAM].Instruction = NULL;
}
if(ulLengthPreProgram)
{
globalGS->pgmList[PREPROGRAM].Length = ulLengthPreProgram;
globalGS->pgmList[PREPROGRAM].Instruction = pvPreProgram;
}
else
{
globalGS->pgmList[PREPROGRAM].Length = ulLengthPreProgram;
globalGS->pgmList[PREPROGRAM].Instruction = NULL;
}
globalGS->maxp = maxp;
globalGS->cvtCount = cvtCount;
globalGS->bCompositeGlyph = FALSE;
}
FS_PUBLIC boolean itrp_bApplyHints(
void * pvGlobalGS)
{
fnt_GlobalGraphicStateType * globalGS;
globalGS = (fnt_GlobalGraphicStateType *)pvGlobalGS;
return (!(globalGS->localParBlock.instructControl & NOGRIDFITFLAG));
}
FS_PUBLIC void itrp_QueryScanInfo(
void * pvGlobalGS,
uint16 * pusScanType,
uint16 * pusScanControl)
{
fnt_GlobalGraphicStateType * globalGS;
globalGS = (fnt_GlobalGraphicStateType *)pvGlobalGS;
*pusScanType = FS_HIWORD(globalGS->localParBlock.scanControl);
*pusScanControl = FS_LOWORD(globalGS->localParBlock.scanControl);
}
FS_PUBLIC void itrp_SetCompositeFlag(
void * pvGlobalGS,
uint8 bCompositeFlag)
{
fnt_GlobalGraphicStateType * globalGS;
globalGS = (fnt_GlobalGraphicStateType *)pvGlobalGS;
globalGS->bCompositeGlyph = bCompositeFlag;
}
/*
* function table
*/
FntFunc function [MAXBYTE_INSTRUCTIONS]
#ifndef FSCFG_NO_INITIALIZED_DATA
=
{
itrp_SVTCA_0, itrp_SVTCA_1, itrp_SPVTCA_0, itrp_SPVTCA_1, itrp_SFVTCA_0, itrp_SFVTCA_1, itrp_SPVTL, itrp_SPVTL,
itrp_SFVTL, itrp_SFVTL, itrp_WPV, itrp_WFV, itrp_RPV, itrp_RFV, itrp_SFVTPV, itrp_ISECT,
itrp_SRP0, itrp_SRP1, itrp_SRP2, itrp_SetElementPtr, itrp_SetElementPtr, itrp_SetElementPtr, itrp_SetElementPtr, itrp_LLOOP,
itrp_RTG, itrp_RTHG, itrp_LMD, itrp_ELSE, itrp_JMPR, itrp_LWTCI, itrp_LSWCI, itrp_LSW,
itrp_DUP, itrp_POP, itrp_CLEAR, itrp_SWAP, itrp_DEPTH, itrp_CINDEX, itrp_MINDEX, itrp_ALIGNPTS,
itrp_RAW, itrp_UTP, itrp_LOOPCALL, itrp_CALL, itrp_FDEF, itrp_IllegalInstruction, itrp_MDAP, itrp_MDAP,
itrp_IUP, itrp_IUP, itrp_SHP, itrp_SHP, itrp_SHC, itrp_SHC, itrp_SHE, itrp_SHE,
itrp_SHPIX, itrp_IP, itrp_MSIRP, itrp_MSIRP, itrp_ALIGNRP, itrp_RTDG, itrp_MIAP, itrp_MIAP,
itrp_NPUSHB, itrp_NPUSHW, itrp_WS, itrp_RS, itrp_WCVT, itrp_RCVT, itrp_RC, itrp_RC,
itrp_WC, itrp_MD, itrp_MD, itrp_MPPEM, itrp_MPS, itrp_FLIPON, itrp_FLIPOFF, itrp_DEBUG,
itrp_LT, itrp_LTEQ, itrp_GT, itrp_GTEQ, itrp_EQ, itrp_NEQ, itrp_ODD, itrp_EVEN,
itrp_IF, itrp_EIF, itrp_AND, itrp_OR, itrp_NOT, itrp_DELTAP1, itrp_SDB, itrp_SDS,
itrp_ADD, itrp_SUB, itrp_DIV, itrp_MUL, itrp_ABS, itrp_NEG, itrp_FLOOR, itrp_CEILING,
itrp_ROUND, itrp_ROUND, itrp_ROUND, itrp_ROUND, itrp_NROUND, itrp_NROUND, itrp_NROUND, itrp_NROUND,
itrp_WCVTFOD, itrp_DELTAP2, itrp_DELTAP3, itrp_DELTAC1, itrp_DELTAC2, itrp_DELTAC3, itrp_SROUND, itrp_S45ROUND,
itrp_JROT, itrp_JROF, itrp_ROFF, itrp_IllegalInstruction, itrp_RUTG, itrp_RDTG, itrp_SANGW, itrp_AA,
itrp_FLIPPT, itrp_FLIPRGON, itrp_FLIPRGOFF, itrp_IDefPatch, itrp_IDefPatch, itrp_SCANCTRL, itrp_SDPVTL, itrp_SDPVTL,
itrp_GETINFO, itrp_IDEF, itrp_ROTATE, itrp_MAX, itrp_MIN, itrp_SCANTYPE, itrp_INSTCTRL, itrp_IDefPatch,
itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch,
itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch,
itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch,
itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch, itrp_IDefPatch,
itrp_PUSHB1, itrp_PUSHB, itrp_PUSHB, itrp_PUSHB, itrp_PUSHB, itrp_PUSHB, itrp_PUSHB, itrp_PUSHB,
itrp_PUSHW1, itrp_PUSHW, itrp_PUSHW, itrp_PUSHW, itrp_PUSHW, itrp_PUSHW, itrp_PUSHW, itrp_PUSHW,
itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP,
itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP,
itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP,
itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP, itrp_MDRP,
itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP,
itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP,
itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP,
itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP, itrp_MIRP
}
#endif /* FSCFG_NO_INITIALIZED_DATA */
;
/* the old itrp_Init function and tables now live in history.fnt - deanb */
#ifdef GET_STACKSPACE
int32 MaxStackSize = 0;
#define PUSH(p, x) \
{ \
if (p - LocalGS.globalGS->stackBase > MaxStackSize) \
MaxStackSize = p - LocalGS.globalGS->stackBase; \
(*(p)++ = (x)); \
}
#else
#define PUSH( p, x ) ( *(p)++ = (x) )
#endif
#define POP( p ) ( *(--p) )
#define BADCOMPILER
#ifdef BADCOMPILER
#define BOOLEANPUSH( p, x ) PUSH( p, ((x) ? 1 : 0) ) /* MPW 3.0 */
#else
#define BOOLEANPUSH( p, x ) PUSH( p, x )
#endif
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#ifdef FSCFG_DEBUG
void CHECK_RANGE (int32 n, int32 min, int32 max);
void CHECK_RANGE (int32 n, int32 min, int32 max)
{
if (n > max || n < min)
ERR_REPORT (ERR_RANGE, n, min, max, 0);
}
void CHECK_ASSERTION (int32 expression);
void CHECK_ASSERTION (int32 expression)
{
if (!expression)
ERR_REPORT (ERR_ASSERTION, expression, 0, 0, 0);
}
void CHECK_CVT (fnt_LocalGraphicStateType* pGS, int32 cvt);
void CHECK_CVT (fnt_LocalGraphicStateType* pGS, int32 cvt)
{
int32 cvtCount = (int32)(pGS->globalGS->cvtCount - 1L);
if ((int32)cvt > cvtCount || (int32)cvt < 0L)
ERR_REPORT (ERR_CVT, cvt, 0, cvtCount, 0);
}
void CHECK_FDEF (fnt_LocalGraphicStateType* pGS, int32 fdef);
void CHECK_FDEF (fnt_LocalGraphicStateType* pGS, int32 fdef)
{
int32 maxFdef = (int32)(pGS->globalGS->maxp->maxFunctionDefs - 1L);
if ((int32)fdef > maxFdef || (int32)fdef < 0L)
ERR_REPORT (ERR_FDEF, fdef, 0, maxFdef, 0);
}
#define CHECK_PROGRAM(a)
void CHECK_ELEMENT (fnt_LocalGraphicStateType* pGS, int32 elem);
void CHECK_ELEMENT (fnt_LocalGraphicStateType* pGS, int32 elem)
{
int32 maxElem = (int32)(pGS->globalGS->maxp->maxElements - 1L);
/*
At least 1 maxElements will always be available
*/
if (!maxElem)
maxElem++;
if ((int32)elem > maxElem || (int32)elem < 0L)
ERR_REPORT (ERR_ELEMENT, elem, 0, maxElem, 0);
}
void CHECK_ELEMENTPTR (fnt_LocalGraphicStateType* pGS, fnt_ElementType*elem);
void CHECK_ELEMENTPTR (fnt_LocalGraphicStateType* pGS, fnt_ElementType*elem)
{
if (elem == &pGS->elements[1])
{
int32 maxctrs, maxpts;
maxctrs = MAX (pGS->globalGS->maxp->maxContours,
pGS->globalGS->maxp->maxCompositeContours);
maxpts = MAX (pGS->globalGS->maxp->maxPoints,
pGS->globalGS->maxp->maxCompositePoints);
if ((int32)elem->nc > (int32)maxctrs || (int32)elem->nc < 1L)
ERR_REPORT (ERR_CONTOUR, elem->nc, 1, maxctrs, 0);
if ((int32)elem->ep[elem->nc-1] > maxpts - 1L ||
(int32)elem->ep[elem->nc-1] < 0L)
ERR_REPORT (ERR_POINT, elem->ep[elem->nc-1], 0, maxpts - 1L, 0);
}
else if (elem != &pGS->elements[0])
ERR_REPORT (ERR_INDEX, elem, &pGS->elements[0], &pGS->elements[1], 0);
}
void CHECK_STORAGE (fnt_LocalGraphicStateType* pGS, int32 index);
void CHECK_STORAGE (fnt_LocalGraphicStateType* pGS, int32 index)
{
int32 maxIndex = (int32)(pGS->globalGS->maxp->maxStorage - 1L);
if ((int32)index > maxIndex || (int32)index < 0L)
ERR_REPORT (ERR_STORAGE, index, 0, maxIndex, 0);
}
void CHECK_STACK (fnt_LocalGraphicStateType* pGS);
void CHECK_STACK (fnt_LocalGraphicStateType* pGS)
{
int32 base = (int32)(pGS->stackPointer - pGS->globalGS->stackBase);
int32 max = (int32)(pGS->globalGS->maxp->maxStackElements - 1L);
if (base > max || base < 0L)
ERR_REPORT (ERR_STACK, base, 0, max, 0);
}
void CHECK_POINT (fnt_LocalGraphicStateType* pGS, fnt_ElementType*elem, int32 pt);
void CHECK_POINT (fnt_LocalGraphicStateType* pGS, fnt_ElementType*elem, int32 pt)
{
CHECK_ELEMENTPTR (pGS, elem);
if (pGS->elements == elem)
{
if ((int32)pt > pGS->globalGS->maxp->maxTwilightPoints - 1L ||
(int32)pt < 0L)
ERR_REPORT (ERR_POINT, pt, 0, pGS->globalGS->maxp->maxTwilightPoints - 1L, 0);
}
else /* phantom points */
{
if ((int32)pt > elem->ep[elem->nc-1] + 2L || (int32)pt < 0L)
ERR_REPORT (ERR_POINT, pt, 0, elem->ep[elem->nc-1] + 2L, 0);
}
}
void CHECK_CONTOUR (fnt_LocalGraphicStateType* pGS, fnt_ElementType*elem, int32 ctr);
void CHECK_CONTOUR (fnt_LocalGraphicStateType* pGS, fnt_ElementType*elem, int32 ctr)
{
CHECK_ELEMENTPTR (pGS, elem);
if ((int32)ctr > elem->nc - 1L || (int32)ctr < 0L)
ERR_REPORT (ERR_CONTOUR, ctr, 0, elem->nc -1L, 0);
}
void CHECK_VECTOR (VECTORTYPE x, VECTORTYPE y);
void CHECK_VECTOR (VECTORTYPE x, VECTORTYPE y)
{
if ( x == 0 && y == 0 )
ERR_REPORT (ERR_VECTOR, x, y, 0, 0);
}
void CHECK_LARGER (int32 min, int32 n);
void CHECK_LARGER (int32 min, int32 n)
{
if ( n <= min )
ERR_REPORT (ERR_LARGER, min, n, 0, 0);
}
void CHECK_INT8 (int32 n);
void CHECK_INT8 (int32 n)
{
if ( n & 0xFFFFFF00 )
ERR_REPORT (ERR_INT8, n, 0, 0, 0);
}
void CHECK_INT16 (int32 n);
void CHECK_INT16 (int32 n)
{
if ( n & 0xFFFF0000 )
ERR_REPORT (ERR_INT16, n, 0, 0, 0);
}
void CHECK_SELECTOR (int32 n);
void CHECK_SELECTOR (int32 n)
{
if ( n & 0xFFF8)
ERR_REPORT (ERR_SELECTOR, n, 0, 0, 0);
}
void CHECK_SUBSTACK (fnt_LocalGraphicStateType* pGS, F26Dot6* pt);
void CHECK_SUBSTACK (fnt_LocalGraphicStateType* pGS, F26Dot6* pt)
{
int32 base = (int32)(pt - pGS->globalGS->stackBase);
int32 max = (int32)(pGS->globalGS->maxp->maxStackElements - 1L);
if (base > max || base < 0L)
ERR_REPORT (ERR_STACK, base, 0, max, 0);
}
void POP_CHECK (F26Dot6*);
void POP_CHECK (F26Dot6* stackPtr)
{
F26Dot6 * base = LocalGS.globalGS->stackBase;
F26Dot6 * max;
max = base + LocalGS.globalGS->maxp->maxStackElements - 1L;
if ( stackPtr <= base)
ERR_REPORT (ERR_STACK, (stackPtr - base - 1L), 0, (max - base), 0);
return;
}
void PUSH_CHECK (F26Dot6*);
void PUSH_CHECK (F26Dot6* stackPtr)
{
F26Dot6 * base = LocalGS.globalGS->stackBase;
F26Dot6 * max;
max = base + LocalGS.globalGS->maxp->maxStackElements - 1L;
if ( stackPtr > max )
ERR_REPORT (ERR_STACK, (stackPtr - base), 0, (max - base), 0);
return;
}
#define CHECK_POP(s) (POP_CHECK(s),POP(s))
#define CHECK_PUSH(s, v) (PUSH_CHECK(s),PUSH(s, v))
#else
#define CHECK_RANGE(a,b,c)
#define CHECK_ASSERTION(a)
#define CHECK_CVT(pgs,b)
#define CHECK_POINT(pgs,b,c)
#define CHECK_CONTOUR(pgs,b,c)
#define CHECK_FDEF(pgs,b)
#define CHECK_PROGRAM(a)
#define CHECK_ELEMENT(pgs,b)
#define CHECK_ELEMENTPTR(pgs,b)
#define CHECK_STORAGE(pgs,b)
#define CHECK_STACK(pgs)
#define CHECK_VECTOR(a,b)
#define CHECK_LARGER(a,b)
#define CHECK_INT8(a)
#define CHECK_INT16(a)
#define CHECK_SELECTOR(a)
#define CHECK_SUBSTACK(pgs,a)
#define CHECK_POP(s) POP(s)
#define CHECK_PUSH(s, v) PUSH(s, v)
#endif
/*@@*/
#define MABS(x) ( (x) < 0 ? (-(x)) : (x) )
#define BIT0( t ) ( (t) & 0x01 )
#define BIT1( t ) ( (t) & 0x02 )
#define BIT2( t ) ( (t) & 0x04 )
#define BIT3( t ) ( (t) & 0x08 )
#define BIT4( t ) ( (t) & 0x10 )
#define BIT5( t ) ( (t) & 0x20 )
#define BIT6( t ) ( (t) & 0x40 )
#define BIT7( t ) ( (t) & 0x80 )
/****** Element Codes *********/
#define SCE0_CODE 0x13
#define SCE1_CODE 0x14
#define SCE2_CODE 0x15
#define SCES_CODE 0x16
/****** Control Codes *********/
#define IF_CODE 0x58
#define ELSE_CODE 0x1B
#define EIF_CODE 0x59
#define ENDF_CODE 0x2d
#define MD_CODE 0x49
/* flags for UTP, IUP, MovePoint */
#define XMOVED 0x01
#define YMOVED 0x02
/* Set default values for all variables in globalGraphicsState DefaultParameterBlock
* Eventually, we should provide for a Default preprogram that could optionally be
* run at this time to provide a different set of default values.
*/
ErrorCode itrp_SetDefaults (
void * pvGlobalGS,
Fixed fxPixelDiameter)
{
fnt_ParameterBlock *par;
fnt_GlobalGraphicStateType * globalGS;
globalGS = (fnt_GlobalGraphicStateType *)pvGlobalGS;
par = &globalGS->defaultParBlock;
par->RoundValue = itrp_RoundToGrid;
par->minimumDistance = FNT_PIXELSIZE;
par->wTCI = FNT_PIXELSIZE * 17 / 16;
par->sWCI = 0;
par->sW = 0;
par->autoFlip = true;
par->deltaBase = 9;
par->deltaShift = 3;
par->angleWeight = 128;
par->scanControl = 0;
par->instructControl = 0;
/* Set up the engine compensation array for the interpreter */
/* This will be indexed into by the booleans in some instructions */
globalGS->engine[0] = globalGS->engine[3] = 0; /* Grey and ? distance */
globalGS->engine[1] = FIXEDTODOT6 (FIXEDSQRT2 - fxPixelDiameter); /* Black distance */
globalGS->engine[2] = -globalGS->engine[1]; /* White distance */
return NO_ERR;
}
/************************************************************************/
/*
* Illegal instruction trap
*/
FS_PRIVATE uint8* itrp_IllegalInstruction (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
FS_UNUSED_PARAMETER(pbyInst);
LocalGS.ercReturn = UNDEFINED_INSTRUCTION_ERR; /* returned to client */
return LocalGS.pbyEndInst; /* stops innerEx loop */
}
/************************************************************************/
/* Scale vector (x,y) to unit length in 2.14 rewrite - 1/25/93 - deanb */
FS_PRIVATE void itrp_Normalize (F26Dot6 x, F26Dot6 y, VECTOR *pVec)
{
Fract fLength;
int32 lSumOfSquares;
int32 lShift;
CHECK_RANGE (x, -32768L << 6, 32767L << 6);
CHECK_RANGE (y, -32768L << 6, 32767L << 6);
if ((x == 0L) && (y == 0L)) /* if null vector in */
{
pVec->x = ONEVECTOR; /* default to unit x vector */
pVec->y = 0;
}
else
{
if ((x < 32767L) && (x > -32768L) && (y < 32767L) && (y > -32768L))
{
lSumOfSquares = (x * x) + (y * y);
lShift = 8 * sizeof(Fract) - 17; /* to get x and y to 2.30 */
while (lSumOfSquares < 0x20000000L)
{
lSumOfSquares <<= 2; /* maximize precision */
lShift++;
}
x <<= lShift;
y <<= lShift; /* keep x and y in step */
}
else
{
while ((x < 0x20000000L) && (x > -0x20000000L) && (y < 0x20000000L) && (y > -0x20000000L))
{
x <<= 1;
y <<= 1;
}
lSumOfSquares = FracMul(x, x) + FracMul(y, y);
}
fLength = FracSqrt(lSumOfSquares);
pVec->x = ROUNDFIXTOINT (FracDiv(x, fLength));
pVec->y = ROUNDFIXTOINT (FracDiv(y, fLength));
}
}
/******************** BEGIN Rounding Routines ***************************/
/*
* Internal rounding routine
*/
F26Dot6 itrp_RoundToDoubleGrid (GSP F26Dot6 xin, F26Dot6 engine)
{
F26Dot6 x = xin;
if (x >= 0)
{
x += engine;
x += FNT_PIXELSIZE / 4;
x &= ~ (FNT_PIXELSIZE / 2 - 1);
}
else
{
x = -x;
x += engine;
x += FNT_PIXELSIZE / 4;
x &= ~ (FNT_PIXELSIZE / 2 - 1);
x = -x;
}
if (( (int32) (xin ^ x)) < 0 && xin)
{
x = 0; /* The sign flipped, make zero */
}
return x;
}
/*
* Internal rounding routine
*/
F26Dot6 itrp_RoundDownToGrid (GSP F26Dot6 xin, F26Dot6 engine)
{
F26Dot6 x = xin;
if (x >= 0)
{
x += engine;
x &= ~ (FNT_PIXELSIZE - 1);
}
else
{
x = -x;
x += engine;
x &= ~ (FNT_PIXELSIZE - 1);
x = -x;
}
if (( (int32) (xin ^ x)) < 0 && xin)
{
x = 0; /* The sign flipped, make zero */
}
return x;
}
/*
* Internal rounding routine
*/
F26Dot6 itrp_RoundUpToGrid (GSP F26Dot6 xin, F26Dot6 engine)
{
F26Dot6 x = xin;
if (x >= 0)
{
x += engine;
x += FNT_PIXELSIZE - 1;
x &= ~ (FNT_PIXELSIZE - 1);
}
else
{
x = -x;
x += engine;
x += FNT_PIXELSIZE - 1;
x &= ~ (FNT_PIXELSIZE - 1);
x = -x;
}
if (( (int32) (xin ^ x)) < 0 && xin)
{
x = 0; /* The sign flipped, make zero */
}
return x;
}
/*
* Internal rounding routine
*/
F26Dot6 itrp_RoundToGrid (GSP F26Dot6 xin, F26Dot6 engine)
{
F26Dot6 x = xin;
if (x >= 0)
{
x += engine;
x += FNT_PIXELSIZE / 2;
x &= ~ (FNT_PIXELSIZE - 1);
}
else
{
x = -x;
x += engine;
x += FNT_PIXELSIZE / 2;
x &= ~ (FNT_PIXELSIZE - 1);
x = -x;
}
if (( (int32) (xin ^ x)) < 0 && xin)
{
x = 0; /* The sign flipped, make zero */
}
return x;
}
/*
* Internal rounding routine
*/
F26Dot6 itrp_RoundToHalfGrid (GSP F26Dot6 xin, F26Dot6 engine)
{
F26Dot6 x = xin;
if (x >= 0)
{
x += engine;
x &= ~ (FNT_PIXELSIZE - 1);
x += FNT_PIXELSIZE / 2;
}
else
{
x = -x;
x += engine;
x &= ~ (FNT_PIXELSIZE - 1);
x += FNT_PIXELSIZE / 2;
x = -x;
}
if (((xin ^ x)) < 0 && xin)
{
x = xin > 0 ? FNT_PIXELSIZE / 2 : -FNT_PIXELSIZE / 2; /* The sign flipped, make equal to smallest valid value */
}
return x;
}
/*
* Internal rounding routine
*/
F26Dot6 itrp_RoundOff (GSP F26Dot6 xin, F26Dot6 engine)
{
F26Dot6 x = xin;
if (x >= 0)
{
x += engine;
}
else
{
x -= engine;
}
if (( (int32) (xin ^ x)) < 0 && xin)
{
x = 0; /* The sign flipped, make zero */
}
return x;
}
/************************************************************************/
/*
* Internal rounding routine
*/
F26Dot6 itrp_SuperRound (GSP F26Dot6 xin, F26Dot6 engine)
{
F26Dot6 x = xin;
fnt_ParameterBlock *pb = &LocalGS.globalGS->localParBlock;
if (x >= 0)
{
x += engine;
x += pb->threshold - pb->phase;
x &= pb->periodMask;
x += pb->phase;
}
else
{
x = -x;
x += engine;
x += pb->threshold - pb->phase;
x &= pb->periodMask;
x += pb->phase;
x = -x;
}
if (( (int32) (xin ^ x)) < 0 && xin)
{
x = xin > 0 ? pb->phase : -pb->phase; /* The sign flipped, make equal to smallest phase */
}
return x;
}
/*
* Internal rounding routine
*/
F26Dot6 itrp_Super45Round (GSP F26Dot6 xin, F26Dot6 engine)
{
F26Dot6 x = xin;
fnt_ParameterBlock *pb = &LocalGS.globalGS->localParBlock;
if (x >= 0)
{
x += engine;
x += pb->threshold - pb->phase;
x = (F26Dot6) VECTORDIV (x, pb->period45);
x &= ~ (FNT_PIXELSIZE - 1);
x = (F26Dot6) VECTORMUL (x, pb->period45);
x += pb->phase;
}
else
{
x = -x;
x += engine;
x += pb->threshold - pb->phase;
x = (F26Dot6) VECTORDIV (x, pb->period45);
x &= ~ (FNT_PIXELSIZE - 1);
x = (F26Dot6) VECTORMUL (x, pb->period45);
x += pb->phase;
x = -x;
}
if (((xin ^ x)) < 0 && xin)
{
x = xin > 0 ? pb->phase : -pb->phase; /* The sign flipped, make equal to smallest phase */
}
return x;
}
/******************** END Rounding Routines ***************************/
/* 3-versions ************************************************************************/
/*
* Moves the point in element by delta (measured against the projection vector)
* along the freedom vector.
*/
FS_PRIVATE void itrp_MovePoint (GSP fnt_ElementType *element, int32 point, F26Dot6 delta)
{
VECTORTYPE pfProj;
VECTORTYPE fx;
VECTORTYPE fy;
pfProj = LocalGS.pfProj;
fx = LocalGS.free.x;
fy = LocalGS.free.y;
CHECK_POINT (&LocalGS, element, point);
if (pfProj != ONEVECTOR)
{
if (fx)
{
if (pfProj == fx) /* if proj.x = 1 */
{
element->x[point] += delta;
}
else
{
element->x[point] += LongMulDiv (delta, (int32)fx, (int32)pfProj);
}
element->f[point] |= XMOVED;
}
if (fy)
{
if (pfProj == fy) /* if proj.y = 1 */
{
element->y[point] += delta;
}
else
{
element->y[point] += LongMulDiv (delta, (int32)fy, (int32)pfProj);
}
element->f[point] |= YMOVED;
}
}
else
{
if (fx)
{
element->x[point] += VECTORMUL (delta, fx);
element->f[point] |= XMOVED;
}
if (fy)
{
element->y[point] += VECTORMUL (delta, fy);
element->f[point] |= YMOVED;
}
}
}
/*
* For use when the projection and freedom vectors coincide along the x-axis.
*/
FS_PRIVATE void itrp_XMovePoint (GSP fnt_ElementType*element, int32 point, F26Dot6 delta)
{
CHECK_POINT (&LocalGS, element, point);
element->x[point] += delta;
element->f[point] |= XMOVED;
}
/*
* For use when the projection and freedom vectors coincide along the y-axis.
*/
FS_PRIVATE void itrp_YMovePoint (GSP fnt_ElementType *element, int32 point, F26Dot6 delta)
{
CHECK_POINT (&LocalGS, element, point);
element->y[point] += delta;
element->f[point] |= YMOVED;
}
/*
* projects x and y into the projection vector.
*/
FS_PRIVATE F26Dot6 itrp_Project (GSP F26Dot6 x, F26Dot6 y)
{
return (F26Dot6) (VECTORMUL (x, LocalGS.proj.x) + VECTORMUL (y, LocalGS.proj.y));
}
/*
* projects x and y into the old projection vector.
*/
FS_PRIVATE F26Dot6 itrp_OldProject (GSP F26Dot6 x, F26Dot6 y)
{
return (F26Dot6) (VECTORMUL (x, LocalGS.oldProj.x) + VECTORMUL (y, LocalGS.oldProj.y));
}
/*
* Projects when the projection vector is along the x-axis
*/
F26Dot6 itrp_XProject (GSP F26Dot6 x, F26Dot6 y)
{
FS_UNUSED_PARAMETER(y);
return (x);
}
/*
* Projects when the projection vector is along the y-axis
*/
F26Dot6 itrp_YProject (GSP F26Dot6 x, F26Dot6 y)
{
FS_UNUSED_PARAMETER(x);
return (y);
}
/*************************************************************************/
/*** Compensation for Transformations ***/
/*
* Internal support routine, keep this guy FAST!!!!!!! <3>
*/
FS_PRIVATE Fixed itrp_GetCVTScale (GSP0)
{
VECTORTYPE pvx, pvy;
fnt_GlobalGraphicStateType *globalGS = LocalGS.globalGS;
Fixed sySq, sxSq, strSq;
/* Do as few Math routines as possible to gain speed */
pvx = LocalGS.proj.x;
pvy = LocalGS.proj.y;
if (pvy)
{
if (pvx)
{
if (LocalGS.cvtDiagonalStretch == 0) /* cache is now invalid */
{
pvy = VECTORDOT (pvy, pvy);
pvx = VECTORDOT (pvx, pvx);
sySq = FixMul (globalGS->cvtStretchY, globalGS->cvtStretchY);
sxSq = FixMul (globalGS->cvtStretchX, globalGS->cvtStretchX);
strSq = FixMul (VECTOR2FIX(pvx),sxSq) + FixMul (VECTOR2FIX(pvy),sySq);
if (strSq > ONEFIX) /* Never happens! */
return ONEFIX;
/* Convert 16.16 to 2.30, compute square root, round to 16.16 */
LocalGS.cvtDiagonalStretch = (FracSqrt (strSq<<14) + (1<<13)) >> 14;
}
return LocalGS.cvtDiagonalStretch;
}
else /* pvy == +1 or -1 */
return globalGS->cvtStretchY;
}
else /* pvx == +1 or -1 */
return globalGS->cvtStretchX;
}
/* Functions for function pointer in local graphic state
*/
FS_PRIVATE F26Dot6 itrp_GetCVTEntryFast (GSP int32 n)
{
CHECK_CVT (&LocalGS, n);
return LocalGS.globalGS->controlValueTable[ n ];
}
FS_PRIVATE F26Dot6 itrp_GetCVTEntrySlow (GSP int32 n)
{
Fixed scale;
CHECK_CVT (&LocalGS, n);
scale = itrp_GetCVTScale (GSA0);
return (F26Dot6) (FixMul (LocalGS.globalGS->controlValueTable[ n ], scale));
}
FS_PRIVATE F26Dot6 itrp_GetSingleWidthFast (GSP0)
{
return LocalGS.globalGS->localParBlock.scaledSW;
}
/*
*
*/
FS_PRIVATE F26Dot6 itrp_GetSingleWidthSlow (GSP0)
{
Fixed scale;
scale = itrp_GetCVTScale (GSA0);
return (F26Dot6) (FixMul (LocalGS.globalGS->localParBlock.scaledSW, scale));
}
/*************************************************************************/
FS_PRIVATE void itrp_ChangeCvtFast (GSP fnt_ElementType*elem, int32 number, F26Dot6 delta)
{
FS_UNUSED_PARAMETER(elem);
CHECK_CVT (&LocalGS, number);
LocalGS.globalGS->controlValueTable[ number ] += delta;
}
/*************************************************************************/
FS_PRIVATE void itrp_ChangeCvtSlow (GSP fnt_ElementType*elem, int32 number, F26Dot6 delta)
{
FS_UNUSED_PARAMETER(elem);
CHECK_CVT (&LocalGS, number);
delta = FixDiv (delta, itrp_GetCVTScale(GSA0));
LocalGS.globalGS->controlValueTable[ number ] += delta;
}
/*************************************************************************/
/*
* This is the tracing interpreter.
*/
FS_PRIVATE void itrp_InnerTraceExecute (GSP uint8 *pbyInst, uint8 *pbyEndInst)
{
int32 lOpCode;
LocalGS.pbyEndInst = pbyEndInst; /* for illegal instruction */
if (pbyInst < pbyEndInst)
{
ERR_START ();
while ((pbyInst < pbyEndInst) && (LocalGS.TraceFunc != NULL))
{
LocalGS.insPtr = pbyInst; /* save for client */
LocalGS.opCode = *pbyInst; /* save for client */
ERR_RECORD (*pbyInst);
LocalGS.TraceFunc (&LocalGS, pbyEndInst);
if (LocalGS.TraceFunc == NULL) /* allow client to break out */
{
break;
}
lOpCode = (int32)*pbyInst;
pbyInst++;
pbyInst = function[ lOpCode ] (GSA pbyInst, lOpCode);
ERR_BREAK ();
}
ERR_END ();
}
}
/*************************************************************************/
/*
* This is the fast non-tracing interpreter inner loop.
*/
#if (!defined(i386) || (defined(FSCFG_FNTERR) || defined(FSCFG_REENTRANT)))
// with the new simplified version of InnerExecute,
// the code generated by mips and alpha compilers is so simple
// that no instructions can be taken out, said BodinD and DaveC agreed.
// Therefore, to optimize we write in assemply only for x86 [bodind]
FS_PRIVATE void itrp_InnerExecute (GSP uint8 *pbyInst, uint8 *pbyEndInst)
{
int32 lOpCode;
ERR_START ();
LocalGS.pbyEndInst = pbyEndInst; /* for illegal instruction */
while (pbyInst < pbyEndInst)
{
ERR_RECORD (*pbyInst);
lOpCode = (int32)*pbyInst; /* opCode no longer saved in LocalGS */
pbyInst++;
pbyInst = function[ lOpCode ] (GSA pbyInst, lOpCode);
ERR_BREAK ();
}
ERR_END ();
}
#else
FS_PRIVATE void itrp_InnerExecute (GSP uint8 *pbyInst, uint8 *pbyEndInst);
#endif
/*************************************************************************/
#ifdef FSCFG_DEBUG
FS_PRIVATE F26Dot6 itrp_GetSingleWidthNil (GSP0);
FS_PRIVATE F26Dot6 itrp_GetCVTEntryNil (GSP int32 n);
FS_PRIVATE F26Dot6 itrp_GetSingleWidthNil (GSP0)
{
ERR_REPORT (ERR_GETSINGLEWIDTHNIL, 0, 0, 0, 0);
return 0;
}
FS_PRIVATE F26Dot6 itrp_GetCVTEntryNil (GSP int32 n)
{
ERR_REPORT (ERR_GETCVTENTRYNIL, 0, 0, 0, 0);
return 0;
}
#endif
/*************************************************************************/
FS_PUBLIC ErrorCode itrp_ExecuteFontPgm(
fnt_ElementType * pTwilightElement,
fnt_ElementType * pGlyphElement,
void * pvGlobalGS,
FntTraceFunc TraceFunc)
{
fnt_GlobalGraphicStateType * globalGS;
globalGS = (fnt_GlobalGraphicStateType *)pvGlobalGS;
globalGS->instrDefCount = 0; /* none allocated yet, always do this, even if there's no fontProgram */
globalGS->pgmIndex = FONTPROGRAM;
if (globalGS->pgmList[FONTPROGRAM].Instruction)
{
return itrp_Execute (
pTwilightElement,
pGlyphElement,
globalGS->pgmList[FONTPROGRAM].Instruction,
globalGS->pgmList[FONTPROGRAM].Instruction +
globalGS->pgmList[FONTPROGRAM].Length,
globalGS,
TraceFunc);
}
return NO_ERR;
}
/*************************************************************************/
FS_PUBLIC ErrorCode itrp_ExecutePrePgm(
fnt_ElementType * pTwilightElement,
fnt_ElementType * pGlyphElement,
void * pvGlobalGS,
FntTraceFunc TraceFunc)
{
ErrorCode result;
fnt_GlobalGraphicStateType * globalGS;
globalGS = (fnt_GlobalGraphicStateType *)pvGlobalGS;
globalGS->init = TRUE;
globalGS->localParBlock = globalGS->defaultParBlock; /* copy gState parameters */
globalGS->pgmIndex = PREPROGRAM;
if (globalGS->pgmList[PREPROGRAM].Instruction)
{
result = itrp_Execute (
pTwilightElement,
pGlyphElement,
globalGS->pgmList[PREPROGRAM].Instruction,
globalGS->pgmList[PREPROGRAM].Instruction + globalGS->pgmList[PREPROGRAM].Length,
globalGS,
TraceFunc);
}
else
{
result = NO_ERR;
}
if (! (globalGS->localParBlock.instructControl & DEFAULTFLAG))
globalGS->defaultParBlock = globalGS->localParBlock; /* change default parameters */
return result;
}
/*************************************************************************/
FS_PUBLIC ErrorCode itrp_ExecuteGlyphPgm(
fnt_ElementType * pTwilightElement,
fnt_ElementType * pGlyphElement,
uint8 * ptr,
uint8 * eptr,
void * pvGlobalGS,
FntTraceFunc TraceFunc,
uint16 * pusScanType,
uint16 * pusScanControl,
boolean * pbChangeScanControl)
{
ErrorCode result;
fnt_GlobalGraphicStateType * globalGS;
globalGS = (fnt_GlobalGraphicStateType *)pvGlobalGS;
result = NO_ERR;
globalGS->init = FALSE;
globalGS->localParBlock = globalGS->defaultParBlock; /* default parameters for glyphs */
if (!(globalGS->localParBlock.instructControl & NOGRIDFITFLAG))
{
result = itrp_Execute (
pTwilightElement,
pGlyphElement,
ptr,
eptr,
globalGS,
TraceFunc);
}
*pbChangeScanControl = (globalGS->localParBlock.scanControl !=
globalGS->defaultParBlock.scanControl);
*pusScanControl = FS_LOWORD(globalGS->localParBlock.scanControl);
*pusScanType = FS_HIWORD(globalGS->localParBlock.scanControl);
return result;
}
/*************************************************************************/
/*
* Executes the font instructions.
*
* Parameter Description
*
* elements points to the character elements. Element 0 is always
* reserved and not used by the actual character.
*
* ptr points at the first instruction.
* eptr points to right after the last instruction
*
* globalGS points at the global graphics state
*
* TraceFunc is pointer to a callback functioned called with a pointer to the
* local graphics state if TraceFunc is not null.
*
* Note: The stuff globalGS is pointing at must remain intact
* between calls to this function.
*/
FS_PRIVATE ErrorCode itrp_Execute (
fnt_ElementType * pTwilightElement,
fnt_ElementType * pGlyphElement,
uint8 * ptr,
uint8 * eptr,
fnt_GlobalGraphicStateType * globalGS,
FntTraceFunc TraceFunc)
{
#ifdef FSCFG_REENTRANT
fnt_LocalGraphicStateType thisLocalGS;
fnt_LocalGraphicStateType* pLocalGS = &thisLocalGS;
#endif
fnt_ElementType aElements[MAX_ELEMENTS];
MEMCPY((void*)&(aElements[TWILIGHTZONE]), (void*)pTwilightElement, sizeof (fnt_ElementType));
MEMCPY((void*)&(aElements[GLYPHELEMENT]), (void*)pGlyphElement, sizeof (fnt_ElementType));
STAT_ON_FNTEXEC; /* start STAT timer */
LocalGS.globalGS = globalGS; /* init Local Graphics State */
LocalGS.elements = aElements;
LocalGS.Pt0 = 0;
LocalGS.Pt1 = 0;
LocalGS.Pt2 = 0;
LocalGS.CE0 = &aElements[GLYPHELEMENT];
LocalGS.CE1 = &aElements[GLYPHELEMENT];
LocalGS.CE2 = &aElements[GLYPHELEMENT];
LocalGS.free.x = ONEVECTOR;
LocalGS.proj.x = ONEVECTOR;
LocalGS.oldProj.x = ONEVECTOR;
LocalGS.free.y = 0;
LocalGS.proj.y = 0;
LocalGS.oldProj.y = 0;
LocalGS.pfProj = ONEVECTOR;
LocalGS.MovePoint = itrp_XMovePoint;
LocalGS.Project = itrp_XProject;
LocalGS.OldProject = itrp_XProject;
LocalGS.loop = 0; /* 1 less than count for faster loops. mrr */
if (globalGS->engine[1] == 0) /* if engine compenstion turned off */
{
LocalGS.MIRPCode = MIRPX; /* default to fast mirp */
}
else
{
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
}
if (globalGS->pgmIndex == FONTPROGRAM)
{
#ifdef FSCFG_DEBUG
LocalGS.GetCVTEntry = itrp_GetCVTEntryNil;
LocalGS.GetSingleWidth = itrp_GetSingleWidthNil;
#else
LocalGS.GetCVTEntry = itrp_GetCVTEntryFast;
LocalGS.GetSingleWidth = itrp_GetSingleWidthFast;
#endif
LocalGS.ChangeCvt = itrp_ChangeCvtFast;
}
else
{
if (globalGS->pixelsPerEm <= 1)
return NO_ERR;
if (globalGS->bSameStretch)
{
LocalGS.GetCVTEntry = itrp_GetCVTEntryFast;
LocalGS.GetSingleWidth = itrp_GetSingleWidthFast;
LocalGS.ChangeCvt = itrp_ChangeCvtFast;
}
else
{
LocalGS.GetCVTEntry = itrp_GetCVTEntrySlow;
LocalGS.GetSingleWidth = itrp_GetSingleWidthSlow;
LocalGS.ChangeCvt = itrp_ChangeCvtSlow;
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
}
if (globalGS->localParBlock.sW) /* We need to scale the single width for this size */
{
globalGS->localParBlock.scaledSW = globalGS->ScaleFuncCVT (&globalGS->scaleCVT, (F26Dot6)(globalGS->localParBlock.sW));
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
}
}
LocalGS.stackPointer = globalGS->stackBase;
LocalGS.TraceFunc = TraceFunc;
LocalGS.ercReturn = NO_ERR; /* default return value */
if (TraceFunc != NULL)
{
LocalGS.Interpreter = itrp_InnerTraceExecute;
}
else
{
LocalGS.Interpreter = itrp_InnerExecute;
}
(*LocalGS.Interpreter) (GSA ptr, eptr);
STAT_OFF_FNTEXEC; /* stop STAT timer */
return LocalGS.ercReturn; /* NO_ERR unless illegal inst */
}
/*************************************************************************/
/*** 2 internal LocalGS.pfProj computation support routines ***/
/*
* Only does the check of LocalGS.pfProj
*/
FS_PRIVATE void itrp_Check_PF_Proj (GSP0)
{
VECTORTYPE pfProj = LocalGS.pfProj;
if (pfProj > -ONESIXTEENTHVECTOR && pfProj < ONESIXTEENTHVECTOR)
{
LocalGS.pfProj = (VECTORTYPE)(pfProj < 0 ? -ONEVECTOR : ONEVECTOR); /* Prevent divide by small number */
}
}
/*
* Computes LocalGS.pfProj and then does the check
*/
FS_PRIVATE void itrp_ComputeAndCheck_PF_Proj (GSP0)
{
VECTORTYPE pfProj;
pfProj = (VECTORTYPE)(VECTORDOT (LocalGS.proj.x, LocalGS.free.x) + VECTORDOT (LocalGS.proj.y, LocalGS.free.y));
if (pfProj > -ONESIXTEENTHVECTOR && pfProj < ONESIXTEENTHVECTOR)
{
pfProj = (VECTORTYPE)(pfProj < 0 ? -ONEVECTOR : ONEVECTOR); /* Prevent divide by small number */
}
LocalGS.pfProj = pfProj;
LocalGS.cvtDiagonalStretch = 0; /* invalidate cache */
}
/******************************************/
/******** The Actual Instructions *********/
/******************************************/
/*
* Set Vectors To Coordinate Axis - Y
*/
FS_PRIVATE uint8* itrp_SVTCA_0 (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.free.x = LocalGS.proj.x = 0;
LocalGS.free.y = LocalGS.proj.y = ONEVECTOR;
LocalGS.MovePoint = itrp_YMovePoint;
LocalGS.Project = itrp_YProject;
LocalGS.OldProject = itrp_YProject;
LocalGS.pfProj = ONEVECTOR;
if (LocalGS.MIRPCode != MIRPG) /* if we haven't fallen back */
{
LocalGS.MIRPCode = MIRPY; /* then use fast mirp */
}
return pbyInst;
}
/*
* Set Vectors To Coordinate Axis - X
*/
FS_PRIVATE uint8* itrp_SVTCA_1 (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.free.x = LocalGS.proj.x = ONEVECTOR;
LocalGS.free.y = LocalGS.proj.y = 0;
LocalGS.MovePoint = itrp_XMovePoint;
LocalGS.Project = itrp_XProject;
LocalGS.OldProject = itrp_XProject;
LocalGS.pfProj = ONEVECTOR;
if (LocalGS.MIRPCode != MIRPG) /* if we haven't fallen back */
{
LocalGS.MIRPCode = MIRPX; /* then use fast mirp */
}
return pbyInst;
}
/*
* Set Projection Vector To Coordinate Axis - Y
*/
FS_PRIVATE uint8* itrp_SPVTCA_0 (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.proj.x = 0;
LocalGS.proj.y = ONEVECTOR;
LocalGS.Project = itrp_YProject;
LocalGS.pfProj = LocalGS.free.y;
itrp_Check_PF_Proj (GSA0);
LocalGS.MovePoint = itrp_MovePoint;
LocalGS.OldProject = LocalGS.Project;
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
return pbyInst;
}
/*
* Set Projection Vector To Coordinate Axis - X
*/
FS_PRIVATE uint8* itrp_SPVTCA_1 (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.proj.x = ONEVECTOR;
LocalGS.proj.y = 0;
LocalGS.Project = itrp_XProject;
LocalGS.pfProj = LocalGS.free.x;
itrp_Check_PF_Proj (GSA0);
LocalGS.MovePoint = itrp_MovePoint;
LocalGS.OldProject = LocalGS.Project;
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
return pbyInst;
}
/*
* Set Freedom Vector to Coordinate Axis - Y
*/
FS_PRIVATE uint8* itrp_SFVTCA_0 (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.free.x = 0;
LocalGS.free.y = ONEVECTOR;
LocalGS.pfProj = LocalGS.proj.y;
itrp_Check_PF_Proj (GSA0);
LocalGS.MovePoint = itrp_MovePoint;
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
return pbyInst;
}
/*
* Set Freedom Vector to Coordinate Axis - X
*/
FS_PRIVATE uint8* itrp_SFVTCA_1 (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.free.x = ONEVECTOR;
LocalGS.free.y = 0;
LocalGS.pfProj = LocalGS.proj.x;
itrp_Check_PF_Proj (GSA0);
LocalGS.MovePoint = itrp_MovePoint;
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
return pbyInst;
}
/*
* Set Projection Vector To Line
*/
FS_PRIVATE uint8* itrp_SPVTL (IPARAM)
{
int32 arg1, arg2;
arg2 = (int32)CHECK_POP (LocalGS.stackPointer);
arg1 = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_POINT (&LocalGS, LocalGS.CE2, arg2);
CHECK_POINT (&LocalGS, LocalGS.CE1, arg1);
itrp_Normalize (LocalGS.CE1->x[arg1] - LocalGS.CE2->x[arg2], LocalGS.CE1->y[arg1] - LocalGS.CE2->y[arg2], &LocalGS.proj);
if (BIT0 (lOpCode))
{
/* rotate 90 degrees */
VECTORTYPE tmp = LocalGS.proj.y;
LocalGS.proj.y = LocalGS.proj.x;
LocalGS.proj.x = (VECTORTYPE)(-tmp);
}
itrp_ComputeAndCheck_PF_Proj (GSA0);
LocalGS.MovePoint = itrp_MovePoint;
LocalGS.Project = itrp_Project;
LocalGS.OldProject = LocalGS.Project;
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
return pbyInst;
}
/*
* Set Dual Projection Vector To Line
*/
FS_PRIVATE uint8* itrp_SDPVTL (IPARAM)
{
int32 arg1, arg2;
arg2 = (int32)CHECK_POP (LocalGS.stackPointer);
arg1 = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_POINT (&LocalGS, LocalGS.CE2, arg2);
CHECK_POINT (&LocalGS, LocalGS.CE1, arg1);
/* Do the current domain */
itrp_Normalize (LocalGS.CE1->x[arg1] - LocalGS.CE2->x[arg2], LocalGS.CE1->y[arg1] - LocalGS.CE2->y[arg2], &LocalGS.proj);
/* Do the old domain */
itrp_Normalize (LocalGS.CE1->ox[arg1] - LocalGS.CE2->ox[arg2], LocalGS.CE1->oy[arg1] - LocalGS.CE2->oy[arg2], &LocalGS.oldProj);
if (BIT0 (lOpCode))
{
/* rotate 90 degrees */
VECTORTYPE tmp = LocalGS.proj.y;
LocalGS.proj.y = LocalGS.proj.x;
LocalGS.proj.x = (VECTORTYPE)(-tmp);
tmp = LocalGS.oldProj.y;
LocalGS.oldProj.y = LocalGS.oldProj.x;
LocalGS.oldProj.x = (VECTORTYPE)(-tmp);
}
itrp_ComputeAndCheck_PF_Proj (GSA0);
LocalGS.MovePoint = itrp_MovePoint;
LocalGS.Project = itrp_Project;
LocalGS.OldProject = itrp_OldProject;
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
return pbyInst;
}
/*
* Set Freedom Vector To Line
*/
FS_PRIVATE uint8* itrp_SFVTL (IPARAM)
{
int32 arg1, arg2;
arg2 = (int32)CHECK_POP (LocalGS.stackPointer);
arg1 = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_POINT (&LocalGS, LocalGS.CE2, arg2);
CHECK_POINT (&LocalGS, LocalGS.CE1, arg1);
itrp_Normalize (LocalGS.CE1->x[arg1] - LocalGS.CE2->x[arg2], LocalGS.CE1->y[arg1] - LocalGS.CE2->y[arg2], &LocalGS.free);
if (BIT0 (lOpCode))
{
/* rotate 90 degrees */
VECTORTYPE tmp = LocalGS.free.y;
LocalGS.free.y = LocalGS.free.x;
LocalGS.free.x = (VECTORTYPE)(-tmp);
}
itrp_ComputeAndCheck_PF_Proj (GSA0);
LocalGS.MovePoint = itrp_MovePoint;
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
return pbyInst;
}
/*
* Write Projection Vector
*/
FS_PRIVATE uint8* itrp_WPV (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.proj.y = (VECTORTYPE) CHECK_POP (LocalGS.stackPointer);
LocalGS.proj.x = (VECTORTYPE) CHECK_POP (LocalGS.stackPointer);
CHECK_VECTOR (LocalGS.proj.x, LocalGS.proj.y);
itrp_ComputeAndCheck_PF_Proj (GSA0);
LocalGS.MovePoint = itrp_MovePoint;
LocalGS.Project = itrp_Project;
LocalGS.OldProject = LocalGS.Project;
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
return pbyInst;
}
/*
* Write Freedom vector
*/
FS_PRIVATE uint8* itrp_WFV (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.free.y = (VECTORTYPE) CHECK_POP (LocalGS.stackPointer);
LocalGS.free.x = (VECTORTYPE) CHECK_POP (LocalGS.stackPointer);
CHECK_VECTOR (LocalGS.free.x, LocalGS.free.y);
itrp_ComputeAndCheck_PF_Proj (GSA0);
LocalGS.MovePoint = itrp_MovePoint;
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
return pbyInst;
}
/*
* Read Projection Vector
*/
FS_PRIVATE uint8* itrp_RPV (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
CHECK_PUSH (LocalGS.stackPointer, LocalGS.proj.x);
CHECK_PUSH (LocalGS.stackPointer, LocalGS.proj.y);
return pbyInst;
}
/*
* Read Freedom Vector
*/
FS_PRIVATE uint8* itrp_RFV (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
CHECK_PUSH (LocalGS.stackPointer, LocalGS.free.x);
CHECK_PUSH (LocalGS.stackPointer, LocalGS.free.y);
return pbyInst;
}
/*
* Set Freedom Vector To Projection Vector
*/
FS_PRIVATE uint8* itrp_SFVTPV (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.free = LocalGS.proj;
LocalGS.pfProj = ONEVECTOR;
LocalGS.MovePoint = itrp_MovePoint;
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
return pbyInst;
}
/*
* itrp_ISECT ()
*
* Computes the intersection of two lines without using floating point!!
*
* (1) Bx + dBx * t0 = Ax + dAx * t1
* (2) By + dBy * t0 = Ay + dAy * t1
*
* 1 => (t1 = Bx - Ax + dBx * t0) / dAx
* +2 => By + dBy * t0 = Ay + dAy/dAx * [ Bx - Ax + dBx * t0 ]
* => t0 * [dAy/dAx * dBx - dBy] = By - Ay - dAy/dAx* (Bx-Ax)
* => t0 (dAy*DBx - dBy*dAx) = dAx (By - Ay) + dAy (Ax-Bx)
* => t0 = [dAx (By-Ay) + dAy (Ax-Bx)] / [dAy*dBx - dBy*dAx]
* => t0 = [dAx (By-Ay) - dAy (Bx-Ax)] / [dBx*dAy - dBy*dAx]
* t0 = N/D
* =>
* N = (By - Ay) * dAx - (Bx - Ax) * dAy;
* D = dBx * dAy - dBy * dAx;
* A simple floating point implementation would only need this, and
* the check to see if D is zero.
* But to gain speed we do some tricks and avoid floating point.
*
*/
FS_PRIVATE uint8* itrp_ISECT (IPARAM)
{
F26Dot6 N, D;
int32 arg1, arg2;
F26Dot6 Bx, By, Ax, Ay;
F26Dot6 dBx, dBy, dAx, dAy;
{
fnt_ElementType*element = LocalGS.CE0;
F26Dot6*stack = LocalGS.stackPointer;
FS_UNUSED_PARAMETER(lOpCode);
arg2 = (int32)CHECK_POP (stack); /* get one line */
arg1 = (int32)CHECK_POP (stack);
CHECK_POINT (&LocalGS, LocalGS.CE0, arg2);
CHECK_POINT (&LocalGS, LocalGS.CE0, arg1);
dAx = element->x[arg2] - (Ax = element->x[arg1]);
dAy = element->y[arg2] - (Ay = element->y[arg1]);
element = LocalGS.CE1;
arg2 = (int32)CHECK_POP (stack); /* get the other line */
arg1 = (int32)CHECK_POP (stack);
CHECK_POINT (&LocalGS, LocalGS.CE1, arg2);
CHECK_POINT (&LocalGS, LocalGS.CE1, arg1);
dBx = element->x[arg2] - (Bx = element->x[arg1]);
dBy = element->y[arg2] - (By = element->y[arg1]);
arg1 = (int32)CHECK_POP (stack); /* get the point number */
CHECK_POINT (&LocalGS, LocalGS.CE2, arg1);
LocalGS.stackPointer = stack;
}
LocalGS.CE2->f[arg1] |= XMOVED | YMOVED;
{
F26Dot6*elementx = LocalGS.CE2->x;
F26Dot6*elementy = LocalGS.CE2->y;
if (dAy == 0)
{
if (dBx == 0)
{
elementx[arg1] = Bx;
elementy[arg1] = Ay;
return pbyInst;
}
N = By - Ay;
D = -dBy;
}
else if (dAx == 0)
{
if (dBy == 0)
{
elementx[arg1] = Ax;
elementy[arg1] = By;
return pbyInst;
}
N = Bx - Ax;
D = -dBx;
}
else if (MABS (dAx) >= MABS (dAy))
{
/* To prevent out of range problems divide both N and D with the max */
N = (By - Ay) - MulDiv26Dot6 (Bx - Ax, dAy, dAx);
D = MulDiv26Dot6 (dBx, dAy, dAx) - dBy;
}
else
{
N = MulDiv26Dot6 (By - Ay, dAx, dAy) - (Bx - Ax);
D = dBx - MulDiv26Dot6 (dBy, dAx, dAy);
}
if (D)
{
elementx[arg1] = Bx + (F26Dot6) MulDiv26Dot6 (dBx, N, D);
elementy[arg1] = By + (F26Dot6) MulDiv26Dot6 (dBy, N, D);
}
else
{
/* degenerate case: parallell lines, put point in the middle */
elementx[arg1] = (Bx + (dBx >> 1) + Ax + (dAx >> 1)) >> 1;
elementy[arg1] = (By + (dBy >> 1) + Ay + (dAy >> 1)) >> 1;
}
}
return pbyInst;
}
/*
* Load Minimum Distance
*/
FS_PRIVATE uint8* itrp_LMD (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.globalGS->localParBlock.minimumDistance = CHECK_POP (LocalGS.stackPointer);
CHECK_LARGER (-1L, LocalGS.globalGS->localParBlock.minimumDistance);
return pbyInst;
}
/*
* Load Control Value Table Cut In
*/
FS_PRIVATE uint8* itrp_LWTCI (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.globalGS->localParBlock.wTCI = CHECK_POP (LocalGS.stackPointer);
CHECK_LARGER (-1L, LocalGS.globalGS->localParBlock.wTCI);
return pbyInst;
}
/*
* Load Single Width Cut In
*/
FS_PRIVATE uint8* itrp_LSWCI (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.globalGS->localParBlock.sWCI = CHECK_POP (LocalGS.stackPointer);
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
CHECK_LARGER (-1L, LocalGS.globalGS->localParBlock.sWCI);
return pbyInst;
}
/*
* Load Single Width , assumes value comes from the original domain, not the cvt or outline
*/
FS_PRIVATE uint8* itrp_LSW (IPARAM)
{
fnt_GlobalGraphicStateType *globalGS = LocalGS.globalGS;
fnt_ParameterBlock *pb = &globalGS->localParBlock;
int32 arg;
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
arg = CHECK_POP (LocalGS.stackPointer);
CHECK_INT16 (arg);
pb->sW = (int16)arg;
CHECK_LARGER (-1L, pb->sW);
pb->scaledSW = globalGS->ScaleFuncCVT (&globalGS->scaleCVT, (F26Dot6)pb->sW); /* measurement should not come from the outline */
return pbyInst;
}
/* these functions were split out from itrp_SetLocalGraphicState - deanb */
FS_PRIVATE uint8* itrp_SRP0 (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.Pt0 = (int32)CHECK_POP (LocalGS.stackPointer);
return pbyInst;
}
FS_PRIVATE uint8* itrp_SRP1 (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.Pt1 = (int32)CHECK_POP (LocalGS.stackPointer);
return pbyInst;
}
FS_PRIVATE uint8* itrp_SRP2 (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.Pt2 = (int32)CHECK_POP (LocalGS.stackPointer);
return pbyInst;
}
FS_PRIVATE uint8* itrp_LLOOP (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.loop = (int32)(CHECK_POP (LocalGS.stackPointer)) - 1;
return pbyInst;
}
FS_PRIVATE uint8* itrp_POP (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
CHECK_POP (LocalGS.stackPointer);
return pbyInst;
}
FS_PRIVATE uint8* itrp_SetElementPtr (IPARAM)
{
int32 arg;
fnt_ElementType * element;
switch (lOpCode)
{
case SCES_CODE:
ERR_OPC ("SCES");
break;
case SCE0_CODE:
ERR_OPC ("SCE0");
break;
case SCE1_CODE:
ERR_OPC ("SCE1");
break;
case SCE2_CODE:
ERR_OPC ("SCE2");
break;
default:
ERR_OPC ("???");
break;
}
arg = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_ELEMENT (&LocalGS, arg);
element = &LocalGS.elements[ arg ];
switch (lOpCode)
{
case SCES_CODE:
LocalGS.CE2 = element;
LocalGS.CE1 = element;
case SCE0_CODE:
LocalGS.CE0 = element;
break;
case SCE1_CODE:
LocalGS.CE1 = element;
break;
case SCE2_CODE:
LocalGS.CE2 = element;
break;
#ifdef FSCFG_DEBUG
default:
ERR_REPORT (ERR_INVOPC, lOpCode, 0, 0, 0);
break;
#endif
}
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
return pbyInst;
}
/*
* Super Round
*/
FS_PRIVATE uint8* itrp_SROUND (IPARAM)
{
fnt_ParameterBlock *pb = &LocalGS.globalGS->localParBlock;
int32 arg1;
int32 arg;
FS_UNUSED_PARAMETER(lOpCode);
arg = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_INT16 (arg);
arg1 = (int32)arg;
itrp_SetRoundValues (GSA arg1, true);
pb->RoundValue = itrp_SuperRound;
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
return pbyInst;
}
/*
* Super Round
*/
FS_PRIVATE uint8* itrp_S45ROUND (IPARAM)
{
fnt_ParameterBlock *pb = &LocalGS.globalGS->localParBlock;
int32 arg1;
int32 arg;
FS_UNUSED_PARAMETER(lOpCode);
arg = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_INT16 (arg);
arg1 = (int32)arg;
itrp_SetRoundValues (GSA arg1, false);
pb->RoundValue = itrp_Super45Round;
LocalGS.MIRPCode = MIRPG; /* fall back to general mirp */
return pbyInst;
}
/*********************************************************************/
/* These routines were split out from SetRoundState */
/* They set the current rounding state, and all but */
/* RoundToGrid cause MIRP to fall back to MIRPG */
FS_PRIVATE uint8* itrp_RTG (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.globalGS->localParBlock.RoundValue = itrp_RoundToGrid;
return pbyInst;
}
FS_PRIVATE uint8* itrp_RTHG (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.globalGS->localParBlock.RoundValue = itrp_RoundToHalfGrid;
LocalGS.MIRPCode = MIRPG;
return pbyInst;
}
FS_PRIVATE uint8* itrp_RTDG (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.globalGS->localParBlock.RoundValue = itrp_RoundToDoubleGrid;
LocalGS.MIRPCode = MIRPG;
return pbyInst;
}
FS_PRIVATE uint8* itrp_ROFF (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.globalGS->localParBlock.RoundValue = itrp_RoundOff;
LocalGS.MIRPCode = MIRPG;
return pbyInst;
}
FS_PRIVATE uint8* itrp_RDTG (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.globalGS->localParBlock.RoundValue = itrp_RoundDownToGrid;
LocalGS.MIRPCode = MIRPG;
return pbyInst;
}
FS_PRIVATE uint8* itrp_RUTG (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.globalGS->localParBlock.RoundValue = itrp_RoundUpToGrid;
LocalGS.MIRPCode = MIRPG;
return pbyInst;
}
/*********************************************************************/
#define FRACSQRT2DIV2 11591
/*
* Internal support routine for the super rounding routines
*/
FS_PRIVATE void itrp_SetRoundValues (GSP int32 arg1, int32 normalRound)
{
int32 tmp;
fnt_ParameterBlock *pb = &LocalGS.globalGS->localParBlock;
tmp = arg1 & 0xC0;
if (normalRound)
{
switch (tmp)
{
case 0x00:
pb->period = FNT_PIXELSIZE / 2;
break;
case 0x40:
pb->period = FNT_PIXELSIZE;
break;
case 0x80:
pb->period = FNT_PIXELSIZE * 2;
break;
default:
pb->period = 999; /* Illegal */
}
pb->periodMask = ~ (pb->period - 1);
}
else
{
pb->period45 = FRACSQRT2DIV2;
switch (tmp)
{
case 0x00:
pb->period45 >>= 1;
break;
case 0x40:
break;
case 0x80:
pb->period45 <<= 1;
break;
default:
pb->period45 = 999; /* Illegal */
}
tmp = (sizeof (pb->period45) * 8 - 2 - FNT_PIXELSHIFT);
pb->period = (int16) ((pb->period45 + (1L << (tmp - 1))) >> tmp); /*convert from 2.30 to 26.6 */
}
tmp = arg1 & 0x30;
switch (tmp)
{
case 0x00:
pb->phase = 0;
break;
case 0x10:
pb->phase = (int16)((pb->period + 2) >> 2);
break;
case 0x20:
pb->phase = (int16)((pb->period + 1) >> 1);
break;
case 0x30:
pb->phase = (int16)((pb->period + pb->period + pb->period + 2) >> 2);
break;
}
tmp = arg1 & 0x0f;
if (tmp == 0)
{
pb->threshold = (int16)(pb->period - 1);
}
else
{
pb->threshold = (int16)(((tmp - 4) * pb->period + 4) >> 3);
}
}
/*
* Read Advance Width
*/
FS_PRIVATE uint8* itrp_RAW (IPARAM)
{
F26Dot6* ox = LocalGS.elements[GLYPHELEMENT].ox;
int32 index = LocalGS.elements[GLYPHELEMENT].ep[LocalGS.elements[GLYPHELEMENT].nc - 1] + 1; /* lsb point */
FS_UNUSED_PARAMETER(lOpCode);
CHECK_PUSH( LocalGS.stackPointer, ox[index+1] - ox[index] );
return pbyInst;
}
/*
* DUPlicate
*/
FS_PRIVATE uint8* itrp_DUP (IPARAM)
{
F26Dot6 top = LocalGS.stackPointer[-1];
FS_UNUSED_PARAMETER(lOpCode);
CHECK_PUSH (LocalGS.stackPointer, top);
return pbyInst;
}
/*
* CLEAR stack
*/
FS_PRIVATE uint8* itrp_CLEAR (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.stackPointer = LocalGS.globalGS->stackBase;
return pbyInst;
}
/*********************************************************************/
/*
* SWAP
*/
FS_PRIVATE uint8* itrp_SWAP (IPARAM)
{
F26Dot6 *pfxStack;
F26Dot6 fxTemp;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
fxTemp = pfxStack[0];
pfxStack[0] = pfxStack[-1];
pfxStack[-1] = fxTemp;
return pbyInst;
}
/*********************************************************************/
/*
* DEPTH
*/
FS_PRIVATE uint8* itrp_DEPTH (IPARAM)
{
F26Dot6 depth = LocalGS.stackPointer - LocalGS.globalGS->stackBase;
FS_UNUSED_PARAMETER(lOpCode);
CHECK_PUSH (LocalGS.stackPointer, depth);
return pbyInst;
}
/*
* Copy INDEXed value
*/
FS_PRIVATE uint8* itrp_CINDEX (IPARAM)
{
int32 arg1;
F26Dot6 tmp, *p;
F26Dot6*stack = LocalGS.stackPointer;
FS_UNUSED_PARAMETER(lOpCode);
arg1 = (int32)CHECK_POP (stack);
tmp = * (p = (stack - arg1));
CHECK_SUBSTACK (&LocalGS, p);
CHECK_PUSH (stack , tmp);
return pbyInst;
}
/*
* Move INDEXed value
*/
FS_PRIVATE uint8* itrp_MINDEX (IPARAM)
{
int32 arg1;
F26Dot6 tmp, *p;
F26Dot6*stack = LocalGS.stackPointer;
FS_UNUSED_PARAMETER(lOpCode);
arg1 = (int32)CHECK_POP (stack);
tmp = * (p = (stack - arg1));
CHECK_SUBSTACK (&LocalGS, p);
if (arg1)
{
do
{
*p = * (p + 1);
p++;
} while (--arg1);
CHECK_POP (stack);
}
CHECK_PUSH (stack, tmp);
LocalGS.stackPointer = stack;
return pbyInst;
}
/*
* Rotate element 3 to the top of the stack <4>
* Thanks to Oliver for the obscure code.
*/
FS_PRIVATE uint8* itrp_ROTATE (IPARAM)
{
F26Dot6 *stack = LocalGS.stackPointer;
F26Dot6 element1 = *--stack;
F26Dot6 element2 = *--stack;
FS_UNUSED_PARAMETER(lOpCode);
*stack = element1;
element1 = *--stack;
*stack = element2;
* (stack + 2) = element1;
return pbyInst;
}
/*********************************************************************/
/*
* Move Direct Absolute Point
*/
FS_PRIVATE uint8* itrp_MDAP (IPARAM)
{
F26Dot6 fxProj;
fnt_ElementType *pCE0;
fnt_ParameterBlock *pb;
int32 iPoint;
pCE0 = LocalGS.CE0;
pb = &LocalGS.globalGS->localParBlock;
iPoint = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_POINT (&LocalGS, pCE0, iPoint);
LocalGS.Pt0 = iPoint;
LocalGS.Pt1 = iPoint;
if (BIT0 (lOpCode))
{
fxProj = (*LocalGS.Project) (GSA pCE0->x[iPoint], pCE0->y[iPoint]);
fxProj = pb->RoundValue (GSA fxProj, LocalGS.globalGS->engine[0]) - fxProj;
}
else
{
fxProj = 0; /* mark the point as touched */
}
(*LocalGS.MovePoint) (GSA pCE0, iPoint, fxProj);
return pbyInst;
}
/*********************************************************************/
/*
* Move Indirect Absolute Point
*/
FS_PRIVATE uint8* itrp_MIAP (IPARAM)
{
int32 iPoint;
int32 iCVTIndex;
F26Dot6 fxNewProj;
F26Dot6 fxOrigProj;
F26Dot6 fxProjDif;
fnt_ElementType *pCE0;
fnt_ParameterBlock *pb;
pCE0 = LocalGS.CE0;
pb = &LocalGS.globalGS->localParBlock;
iCVTIndex = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_CVT (&LocalGS, iCVTIndex);
fxNewProj = LocalGS.GetCVTEntry (GSA iCVTIndex);
iPoint = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_POINT (&LocalGS, pCE0, iPoint);
LocalGS.Pt0 = iPoint;
LocalGS.Pt1 = iPoint;
if (pCE0 == &LocalGS.elements[TWILIGHTZONE])
{
pCE0->x[iPoint] = (F26Dot6) VECTORMUL (fxNewProj, LocalGS.proj.x);
pCE0->ox[iPoint] = pCE0->x[iPoint];
pCE0->y[iPoint] = (F26Dot6) VECTORMUL (fxNewProj, LocalGS.proj.y);
pCE0->oy[iPoint] = pCE0->y[iPoint];
}
fxOrigProj = (*LocalGS.Project) (GSA pCE0->x[iPoint], pCE0->y[iPoint]);
if (BIT0 (lOpCode))
{
fxProjDif = fxNewProj - fxOrigProj;
if (fxProjDif < 0)
{
fxProjDif = -fxProjDif;
}
if (fxProjDif > pb->wTCI)
{
fxNewProj = fxOrigProj;
}
fxNewProj = pb->RoundValue (GSA fxNewProj, LocalGS.globalGS->engine[0]);
}
(*LocalGS.MovePoint) (GSA pCE0, iPoint, fxNewProj - fxOrigProj);
return pbyInst;
}
/*********************************************************************/
FS_PRIVATE uint8* itrp_IUP (IPARAM)
{
fnt_ElementType *pCE2;
int32 *alOrig; /* original outline array */
int32 *plOrig;
int32 *plOrigTouch2; /* for loop stop */
int32 *plOrigEnd;
int32 lOrig1; /* touched point 1 */
int32 lOrig2; /* touched point 2 */
int32 lOrigMin; /* min coord touched point */
int32 lOrigDelta;
int32 lOrigCorr;
F26Dot6 *afxScaled; /* scaled outline array */
F26Dot6 *pfxScaled;
F26Dot6 fxScaledMax;
F26Dot6 fxScaledMin;
F26Dot6 fxScaledCoord;
F26Dot6 fxMovedMax; /* hint movement of max */
F26Dot6 fxMovedMin; /* hint movement of min */
F26Dot6 *afxHinted; /* hinted outline array */
F26Dot6 *pfxHinted;
F26Dot6 fxHintedMax;
F26Dot6 fxHintedMin;
F26Dot6 fxHintedDelta;
uint8 *abyFlags; /* point flags array */
uint8 byMask;
int32 iPt; /* current point index */
int32 iStartPt; /* start of contour */
int32 iEndPt; /* end of contour */
int32 iStopPt; /* touched point indicates completion */
int32 iTouch1;
int32 iTouch2;
int32 iMin;
int32 iMax;
int32 iContour;
int32 lTemp;
Fixed fRatio;
STAT_ON_IUP; /* start STAT timer */
pCE2 = LocalGS.CE2;
abyFlags = pCE2->f;
if (lOpCode & 0x01) /* use x coordinates */
{
afxHinted = pCE2->x;
afxScaled = pCE2->ox;
if( LocalGS.globalGS->bCompositeGlyph )
{
alOrig = pCE2->ox;
}
else
{
alOrig = pCE2->oox;
}
byMask = XMOVED;
}
else /* use y coordinates */
{
afxHinted = pCE2->y;
afxScaled = pCE2->oy;
if( LocalGS.globalGS->bCompositeGlyph )
{
alOrig = pCE2->oy;
}
else
{
alOrig = pCE2->ooy;
}
byMask = YMOVED;
}
for (iContour = 0; iContour < pCE2->nc; iContour++)
{
iStartPt = pCE2->sp[iContour];
iEndPt = pCE2->ep[iContour];
plOrigEnd = &alOrig[iEndPt]; /* for limit check */
iPt = iStartPt;
while (!(abyFlags[iPt] & byMask) && (iPt <= iEndPt))
{
iPt++;
}
if (iPt <= iEndPt) /* if any points are touched */
{
iStopPt = iPt; /* save for done condition */
do /* for each contour segment */
{
do /* find next untouched point */
{
iTouch1 = iPt;
iPt++;
if (iPt > iEndPt)
{
iPt = iStartPt;
}
} while ((abyFlags[iPt] & byMask) && iPt != iStopPt);
if (iPt != iStopPt)
{
iTouch2 = iPt;
do /* find next touched point */
{
iTouch2++;
if (iTouch2 > iEndPt)
{
iTouch2 = iStartPt;
}
} while (!(abyFlags[iTouch2] & byMask));
lOrig1 = alOrig[iTouch1];
lOrig2 = alOrig[iTouch2];
if (lOrig1 < lOrig2)
{
lOrigMin = lOrig1;
lOrigDelta = lOrig2 - lOrig1;
iMin = iTouch1;
iMax = iTouch2;
}
else
{
lOrigMin = lOrig2;
lOrigDelta = lOrig1 - lOrig2;
iMin = iTouch2;
iMax = iTouch1;
}
fxHintedMin = afxHinted[iMin];
fxScaledMin = afxScaled[iMin];
fxMovedMin = fxHintedMin - fxScaledMin;
if (lOrigDelta != 0L)
{
fxScaledMax = afxScaled[iMax];
fxHintedMax = afxHinted[iMax];
fxMovedMax = fxHintedMax - fxScaledMax;
fxHintedDelta = fxHintedMax - fxHintedMin;
if (lOrigDelta < 32768 && fxHintedDelta < 32768)
{
plOrig = &alOrig[iPt]; /* set up pointers */
pfxScaled = &afxScaled[iPt];
pfxHinted = &afxHinted[iPt];
lOrigCorr = lOrigDelta >> 1;
plOrigTouch2 = &alOrig[iTouch2]; /* set limits */
while (plOrig < plOrigTouch2) /* if not across start/end */
{
fxScaledCoord = *pfxScaled;
if ((fxScaledCoord > fxScaledMin) && (fxScaledCoord < fxScaledMax))
{
lTemp = SHORTMUL (*plOrig - lOrigMin, fxHintedDelta);
lTemp += lOrigCorr;
lTemp /= lOrigDelta;
*pfxHinted = (F26Dot6)lTemp + fxHintedMin;
}
else if (fxScaledCoord >= fxScaledMax)
{
*pfxHinted = fxScaledCoord + fxMovedMax;
}
else
{
*pfxHinted = fxScaledCoord + fxMovedMin;
}
plOrig++;
pfxScaled++;
pfxHinted++;
} /* end of time critical loop */
while (plOrig != plOrigTouch2) /* if points span start/end */
{
fxScaledCoord = *pfxScaled;
if ((fxScaledCoord > fxScaledMin) && (fxScaledCoord < fxScaledMax))
{
lTemp = SHORTMUL (*plOrig - lOrigMin, fxHintedDelta);
lTemp += lOrigCorr;
lTemp /= lOrigDelta;
*pfxHinted = (F26Dot6)lTemp + fxHintedMin;
}
else if (fxScaledCoord >= fxScaledMax)
{
*pfxHinted = fxScaledCoord + fxMovedMax;
}
else
{
*pfxHinted = fxScaledCoord + fxMovedMin;
}
plOrig++;
pfxScaled++;
pfxHinted++;
if (plOrig > plOrigEnd)
{
plOrig = &alOrig[iStartPt];
pfxScaled = &afxScaled[iStartPt];
pfxHinted = &afxHinted[iStartPt];
}
}
iPt = iTouch2; /* keep in step */
}
else /* if too big for 32 bit product */
{
fRatio = FixDiv (fxHintedDelta, lOrigDelta);
while (iPt != iTouch2)
{
lTemp = afxScaled[iPt];
if (lTemp <= fxScaledMin)
{
lTemp += fxMovedMin;
}
else if (lTemp >= fxScaledMax)
{
lTemp += fxMovedMax;
}
else
{
lTemp = alOrig[iPt];
lTemp -= lOrigMin;
lTemp = FixMul (lTemp, fRatio);
lTemp += fxHintedMin;
}
afxHinted[iPt] = (F26Dot6)lTemp;
if (iPt < iEndPt)
iPt++;
else
iPt = iStartPt;
}
} /* endif (lOrigDelta < 32768 && fxHintedDelta < 32768) */
}
else /* if (lOrigDelta == 0L) */
{
while (iPt != iTouch2)
{
afxHinted[iPt] += fxMovedMin;
if (iPt < iEndPt)
iPt++;
else
iPt = iStartPt;
}
} /* endif (lOrigDelta != 0L) */
} /* endif (iPt != iStopPt) */
} while (iPt != iStopPt); /* until contour is closed */
} /* endif (iPt <= iEndPt) */
}
/* next contour */
STAT_OFF_IUP; /* stop STAT timer */
return pbyInst;
}
/*********************************************************************/
FS_PRIVATE fnt_ElementType* itrp_SH_Common (GSP F26Dot6*dx, F26Dot6*dy, int32*point, int32 lOpCode)
{
F26Dot6 proj;
int32 pt;
fnt_ElementType * element;
if (BIT0 (lOpCode))
{
pt = LocalGS.Pt1;
element = LocalGS.CE0;
}
else
{
pt = LocalGS.Pt2;
element = LocalGS.CE1;
}
proj = (*LocalGS.Project) (GSA element->x[pt] - element->ox[pt], element->y[pt] - element->oy[pt]);
if (LocalGS.pfProj != ONEVECTOR)
{
if (LocalGS.free.x)
*dx = (F26Dot6) LongMulDiv (proj, (int32)LocalGS.free.x, (int32)LocalGS.pfProj);
if (LocalGS.free.y)
*dy = (F26Dot6) LongMulDiv (proj, (int32)LocalGS.free.y, (int32)LocalGS.pfProj);
}
else
{
if (LocalGS.free.x)
*dx = (F26Dot6) VECTORMUL (proj, LocalGS.free.x);
if (LocalGS.free.y)
*dy = (F26Dot6) VECTORMUL (proj, LocalGS.free.y);
}
*point = pt;
return element;
}
/*********************************************************************/
FS_PRIVATE void itrp_SHP_Common (GSP F26Dot6 dx, F26Dot6 dy)
{
fnt_ElementType *CE2;
int32 count;
int32 point;
CE2 = LocalGS.CE2;
count = LocalGS.loop + 1; /* faster for ms c8 */
while (count != 0)
{
point = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_POINT (&LocalGS, LocalGS.CE2, point);
if (LocalGS.free.x)
{
CE2->x[point] += dx;
CE2->f[point] |= XMOVED;
}
if (LocalGS.free.y)
{
CE2->y[point] += dy;
CE2->f[point] |= YMOVED;
}
count--;
}
LocalGS.loop = 0;
}
/*********************************************************************/
/*
* SHift Point
*/
FS_PRIVATE uint8* itrp_SHP (IPARAM)
{
F26Dot6 dx, dy;
int32 point;
itrp_SH_Common (GSA &dx, &dy, &point, lOpCode);
itrp_SHP_Common (GSA dx, dy);
return pbyInst;
}
/*
* SHift Contour
*/
FS_PRIVATE uint8* itrp_SHC (IPARAM)
{
fnt_ElementType *element;
F26Dot6 dx, dy;
int32 contour, point;
{
F26Dot6 x, y;
int32 pt;
element = itrp_SH_Common (GSA &x, &y, &pt, lOpCode);
point = pt;
dx = x;
dy = y;
}
contour = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_CONTOUR (&LocalGS, LocalGS.CE2, contour);
{
VECTORTYPE fvx = LocalGS.free.x;
VECTORTYPE fvy = LocalGS.free.y;
fnt_ElementType*CE2 = LocalGS.CE2;
int32 currPt = CE2->sp[contour];
int32 count = CE2->ep[contour] - currPt;
CHECK_POINT (&LocalGS, CE2, currPt + count);
for (; count >= 0; --count)
{
if (currPt != point || element != CE2)
{
if (fvx)
{
CE2->x[currPt] += dx;
CE2->f[currPt] |= XMOVED;
}
if (fvy)
{
CE2->y[currPt] += dy;
CE2->f[currPt] |= YMOVED;
}
}
currPt++;
}
}
return pbyInst;
}
/*********************************************************************/
/*
* SHift Element rewritten 7/29/93 deanb
*
* Flags are no longer set to show touch in x or y direction
*/
FS_PRIVATE uint8* itrp_SHE (IPARAM)
{
fnt_ElementType *element;
F26Dot6 fxDX, fxDY;
int32 lFirstPt, lRefPt, lLastPt, arg1;
F26Dot6 fxSaveX; /* for ref point restoration */
F26Dot6 fxSaveY;
F26Dot6 *pfxX, *pfxStopX; /* temporary element pointers */
F26Dot6 *pfxY, *pfxStopY;
element = itrp_SH_Common (GSA &fxDX, &fxDY, &lRefPt, lOpCode);
arg1 = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_ELEMENT (&LocalGS, arg1);
lLastPt = LocalGS.elements[arg1].ep[LocalGS.elements[arg1].nc - 1];
CHECK_POINT (&LocalGS, &LocalGS.elements[arg1], lLastPt);
lFirstPt = LocalGS.elements[arg1].sp[0];
CHECK_POINT (&LocalGS, &LocalGS.elements[arg1], lFirstPt);
if (element == &LocalGS.elements[arg1]) /* if ref pt is in same zone */
{
fxSaveX = LocalGS.elements[arg1].x[lRefPt];
fxSaveY = LocalGS.elements[arg1].y[lRefPt];
}
if (LocalGS.free.x != 0)
{
pfxX = &LocalGS.elements[arg1].x[lFirstPt];
pfxStopX = &LocalGS.elements[arg1].x[lLastPt];
while (pfxX <= pfxStopX)
{
*pfxX += fxDX; /* shift each point in x */
pfxX++;
}
}
if (LocalGS.free.y != 0)
{
pfxY = &LocalGS.elements[arg1].y[lFirstPt];
pfxStopY = &LocalGS.elements[arg1].y[lLastPt];
while (pfxY <= pfxStopY)
{
*pfxY += fxDY; /* shift each point in y */
pfxY++;
}
}
if (element == &LocalGS.elements[arg1]) /* if ref pt is in same zone */
{
LocalGS.elements[arg1].x[lRefPt] = fxSaveX;
LocalGS.elements[arg1].y[lRefPt] = fxSaveY;
}
return pbyInst;
}
/*********************************************************************/
/*
* SHift point by PIXel amount
*/
FS_PRIVATE uint8* itrp_SHPIX (IPARAM)
{
F26Dot6 proj, dx, dy;
FS_UNUSED_PARAMETER(lOpCode);
proj = CHECK_POP (LocalGS.stackPointer);
if (LocalGS.free.x)
dx = (F26Dot6) VECTORMUL (proj, LocalGS.free.x);
if (LocalGS.free.y)
dy = (F26Dot6) VECTORMUL (proj, LocalGS.free.y);
itrp_SHP_Common (GSA dx, dy);
return pbyInst;
}
/*********************************************************************/
/*
* Interpolate Point
*/
uint8* itrp_IP (IPARAM)
{
int32 arg1;
int32 RP1;
int32 RP2;
int32 cLoop;
fnt_ElementType *pCE0;
fnt_ElementType *pCE1;
fnt_ElementType *pCE2;
fnt_ElementType *pTwilight;
F26Dot6 x_RP1;
F26Dot6 ox_RP1;
F26Dot6 *pCE1_ox;
F26Dot6 *pCE2_ox;
F26Dot6 y_RP1;
F26Dot6 oy_RP1;
F26Dot6 *pCE1_oy;
F26Dot6 *pCE2_oy;
F26Dot6 oldRange;
F26Dot6 proj;
F26Dot6 fxDelta;
F26Dot6 *pfxStack;
FntMoveFunc MovePoint;
FntProject Project;
FS_UNUSED_PARAMETER(lOpCode);
cLoop = LocalGS.loop + 1; /* faster for ms c8 */
pCE0 = LocalGS.CE0;
pCE1 = LocalGS.CE1;
pCE2 = LocalGS.CE2;
pTwilight = &LocalGS.elements[TWILIGHTZONE];
RP1 = LocalGS.Pt1;
RP2 = LocalGS.Pt2;
pfxStack = LocalGS.stackPointer;
MovePoint = LocalGS.MovePoint;
Project = LocalGS.Project;
if (pCE0 == pTwilight || pCE1 == pTwilight || pCE2 == pTwilight || LocalGS.globalGS->bCompositeGlyph)
{
ox_RP1 = pCE0->ox[RP1];
oy_RP1 = pCE0->oy[RP1];
pCE1_ox = pCE1->ox;
pCE1_oy = pCE1->oy;
pCE2_ox = pCE2->ox;
pCE2_oy = pCE2->oy;
}
else
{
ox_RP1 = pCE0->oox[RP1];
oy_RP1 = pCE0->ooy[RP1];
pCE1_ox = pCE1->oox;
pCE1_oy = pCE1->ooy;
pCE2_ox = pCE2->oox;
pCE2_oy = pCE2->ooy;
}
x_RP1 = pCE0->x[RP1];
y_RP1 = pCE0->y[RP1];
oldRange = LocalGS.OldProject (GSA pCE1_ox[RP2] - ox_RP1, pCE1_oy[RP2] - oy_RP1);
if (oldRange != 0) /* this should always happen */
{
if (MovePoint == itrp_XMovePoint) /* so project is also xproject */
{
proj = pCE1->x[RP2] - x_RP1;
while (cLoop != 0)
{
arg1 = (int32)CHECK_POP (pfxStack);
CHECK_POINT (&LocalGS, pCE2, arg1);
fxDelta = pCE2_ox[arg1] - ox_RP1;
fxDelta = (F26Dot6)MulDiv26Dot6 (proj, fxDelta, oldRange);
pCE2->x[arg1] = fxDelta + x_RP1;
pCE2->f[arg1] |= XMOVED;
cLoop--;
}
}
else if (MovePoint == itrp_YMovePoint) /* so project is also yproject */
{
proj = pCE1->y[RP2] - y_RP1;
while (cLoop != 0)
{
arg1 = (int32)CHECK_POP (pfxStack);
CHECK_POINT (&LocalGS, pCE2, arg1);
fxDelta = pCE2_oy[arg1] - oy_RP1;
fxDelta = (F26Dot6) MulDiv26Dot6(proj, fxDelta, oldRange);
pCE2->y[arg1] = fxDelta + y_RP1;
pCE2->f[arg1] |= YMOVED;
cLoop--;
}
}
else /* if (MovePoint == itrp_MovePoint) */
{
proj = Project (GSA pCE1->x[RP2] - x_RP1, pCE1->y[RP2] - y_RP1);
while (cLoop != 0)
{
arg1 = (int32)CHECK_POP (pfxStack);
CHECK_POINT (&LocalGS, pCE2, arg1);
fxDelta = Project (GSA pCE2_ox[arg1] - ox_RP1, pCE2_oy[arg1] - oy_RP1);
fxDelta = (F26Dot6) MulDiv26Dot6(proj, fxDelta, oldRange);
MovePoint (GSA pCE2, arg1, fxDelta -
Project (GSA pCE2->x[arg1] - x_RP1, pCE2->y[arg1] - y_RP1) );
cLoop--;
}
}
}
else /* if (oldRange == 0) */
/* this should never happen, but for safety's sake... */
{
while (cLoop != 0)
{
arg1 = (int32)CHECK_POP (pfxStack);
CHECK_POINT (&LocalGS, pCE2, arg1);
fxDelta = Project (GSA pCE2_ox[arg1] - ox_RP1, pCE2_oy[arg1] - oy_RP1);
MovePoint (GSA pCE2, arg1, fxDelta -
Project (GSA pCE2->x[arg1] - x_RP1, pCE2->y[arg1] - y_RP1) );
cLoop--;
}
} /* endif (oldRange != 0) */
LocalGS.stackPointer = pfxStack;
LocalGS.loop = 0;
return pbyInst;
}
/*********************************************************************/
/*
* Move Stack Indirect Relative Point
*/
uint8* itrp_MSIRP (IPARAM)
{
int32 iPt0;
int32 iPt2; /* point # */
F26Dot6 fxDist; /* distance */
F26Dot6 fxPosition;
fnt_ElementType *pCE0;
fnt_ElementType *pCE1;
pCE0 = LocalGS.CE0;
pCE1 = LocalGS.CE1;
iPt0 = LocalGS.Pt0;
fxDist = CHECK_POP (LocalGS.stackPointer);
iPt2 = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_POINT (&LocalGS, pCE1, iPt2);
if (pCE1 == &LocalGS.elements[TWILIGHTZONE])
{
pCE1->ox[iPt2] = pCE0->ox[iPt0] + (F26Dot6) VECTORMUL (fxDist, LocalGS.proj.x);
pCE1->oy[iPt2] = pCE0->oy[iPt0] + (F26Dot6) VECTORMUL (fxDist, LocalGS.proj.y);
pCE1->x[iPt2] = pCE1->ox[iPt2];
pCE1->y[iPt2] = pCE1->oy[iPt2];
}
fxPosition = (*LocalGS.Project) (GSA pCE1->x[iPt2] - pCE0->x[iPt0], pCE1->y[iPt2] - pCE0->y[iPt0]);
(*LocalGS.MovePoint) (GSA pCE1, iPt2, fxDist - fxPosition);
LocalGS.Pt1 = iPt0;
LocalGS.Pt2 = iPt2;
if (BIT0 (lOpCode))
{
LocalGS.Pt0 = iPt2; /* move the reference point */
}
return pbyInst;
}
/*********************************************************************/
/*
* Align Relative Point
*/
FS_PRIVATE uint8* itrp_ALIGNRP (IPARAM)
{
fnt_ElementType*ce1 = LocalGS.CE1;
F26Dot6 pt0x = LocalGS.CE0->x[LocalGS.Pt0];
F26Dot6 pt0y = LocalGS.CE0->y[LocalGS.Pt0];
FS_UNUSED_PARAMETER(lOpCode);
for (; LocalGS.loop >= 0; --LocalGS.loop)
{
int32 ptNum = (int32)CHECK_POP (LocalGS.stackPointer);
F26Dot6 proj;
CHECK_POINT (&LocalGS, ce1, ptNum);
proj = -(* LocalGS.Project) (GSA ce1->x[ptNum] - pt0x, ce1->y[ptNum] - pt0y);
(*LocalGS.MovePoint) (GSA ce1, ptNum, proj);
}
LocalGS.loop = 0;
return pbyInst;
}
/*
* Align Two Points (by moving both of them)
*/
FS_PRIVATE uint8* itrp_ALIGNPTS (IPARAM)
{
int32 pt1, pt2;
F26Dot6 move1, dist;
FS_UNUSED_PARAMETER(lOpCode);
pt2 = (int32)CHECK_POP (LocalGS.stackPointer); /* point # 2 */
pt1 = (int32)CHECK_POP (LocalGS.stackPointer); /* point # 1 */
CHECK_POINT (&LocalGS, LocalGS.CE1, pt2);
CHECK_POINT (&LocalGS, LocalGS.CE0, pt1);
/* We do not have to check if we are in character element zero (the twilight zone)
since both points already have to have defined values before we execute this instruction */
dist = LocalGS.CE1->x[pt2] - LocalGS.CE0->x[pt1];
move1 = LocalGS.CE1->y[pt2] - LocalGS.CE0->y[pt1];
if (LocalGS.Project != itrp_XProject)
{
if (LocalGS.Project == itrp_YProject)
dist = move1;
else
dist = (*LocalGS.Project) (GSA dist, move1);
}
move1 = dist >> 1;
(*LocalGS.MovePoint) (GSA LocalGS.CE0, pt1, move1);
(*LocalGS.MovePoint) (GSA LocalGS.CE1, pt2, move1 - dist);
return pbyInst;
}
/*
* Set Angle Weight
*/
FS_PRIVATE uint8* itrp_SANGW (IPARAM)
{
int32 arg;
FS_UNUSED_PARAMETER(lOpCode);
arg = CHECK_POP (LocalGS.stackPointer);
CHECK_INT16 (arg);
LocalGS.globalGS->localParBlock.angleWeight = (int16)arg;
return pbyInst;
}
/*
* Flip Point
*/
FS_PRIVATE uint8* itrp_FLIPPT (IPARAM)
{
uint8 *onCurve = LocalGS.CE0->onCurve;
F26Dot6*stack = LocalGS.stackPointer;
int32 count = LocalGS.loop;
FS_UNUSED_PARAMETER(lOpCode);
for (; count >= 0; --count)
{
int32 point = (int32)CHECK_POP (stack);
CHECK_POINT (&LocalGS, LocalGS.CE0, point);
onCurve[ point ] ^= ONCURVE;
}
LocalGS.loop = 0;
LocalGS.stackPointer = stack;
return pbyInst;
}
/*
* Flip On a Range
*/
FS_PRIVATE uint8* itrp_FLIPRGON (IPARAM)
{
int32 lo, hi;
int32 count;
uint8 *onCurve = LocalGS.CE0->onCurve;
F26Dot6*stack = LocalGS.stackPointer;
FS_UNUSED_PARAMETER(lOpCode);
hi = (int32)CHECK_POP (stack);
CHECK_POINT (&LocalGS, LocalGS.CE0, hi);
lo = (int32)CHECK_POP (stack);
CHECK_POINT (&LocalGS, LocalGS.CE0, lo);
onCurve += lo;
for (count = (int32) (hi - lo); count >= 0; --count)
*onCurve++ |= ONCURVE;
LocalGS.stackPointer = stack;
return pbyInst;
}
/*
* Flip On a Range
*/
FS_PRIVATE uint8* itrp_FLIPRGOFF (IPARAM)
{
int32 lo, hi;
int32 count;
uint8 *onCurve = LocalGS.CE0->onCurve;
FS_UNUSED_PARAMETER(lOpCode);
hi = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_POINT (&LocalGS, LocalGS.CE0, hi);
lo = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_POINT (&LocalGS, LocalGS.CE0, lo);
onCurve += lo;
for (count = (int32) (hi - lo); count >= 0; --count)
*onCurve++ &= ~ONCURVE;
return pbyInst;
}
/* 4/22/90 rwb - made more general
* Sets lower 16 flag bits of ScanControl variable. Sets scanContolIn if we are in one
* of the preprograms; else sets scanControlOut.
*
* stack: value => -;
*
*/
FS_PRIVATE uint8* itrp_SCANCTRL (IPARAM)
{
fnt_GlobalGraphicStateType *globalGS = LocalGS.globalGS;
fnt_ParameterBlock *pb = &globalGS->localParBlock;
int32 arg;
FS_UNUSED_PARAMETER(lOpCode);
arg = CHECK_POP (LocalGS.stackPointer);
CHECK_INT16 (arg);
pb->scanControl = (pb->scanControl & 0xFFFF0000) | arg;
return pbyInst;
}
/* 5/24/90 rwb
* Sets upper 16 bits of ScanControl variable. Sets scanContolIn if we are in one
* of the preprograms; else sets scanControlOut.
*/
FS_PRIVATE uint8* itrp_SCANTYPE (IPARAM)
{
fnt_GlobalGraphicStateType *globalGS;
fnt_ParameterBlock *pb;
int32 *scanPtr;
int32 arg;
FS_UNUSED_PARAMETER(lOpCode);
globalGS = LocalGS.globalGS;
pb = &globalGS->localParBlock;
scanPtr = (int32*)&(pb->scanControl);
arg = CHECK_POP (LocalGS.stackPointer);
CHECK_INT16 (arg);
/* how it was:
CHECK_SCANMODE (arg);
if (arg == 0)
*scanPtr &= 0xFFFF;
else if (arg == 1)
*scanPtr = (*scanPtr & 0xFFFF) | STUBCONTROL;
else if (arg == 2)
*scanPtr = (*scanPtr & 0xFFFF) | NODOCONTROL;
*/
/* now any 8 bit value may be passed to the scan converter */
*scanPtr = (*scanPtr & 0xFFFF) | (arg << 16);
return pbyInst;
}
/* 6/28/90 rwb
* Sets instructControl flags in global graphic state. Only legal in pre program.
* A selector is used to choose the flag to be set.
* Bit0 - NOGRIDFITFLAG - if set, then truetype instructions are not executed.
* A font may want to use the preprogram to check if the glyph is rotated or
* transformed in such a way that it is better to not gridfit the glyphs.
* Bit1 - DEFAULTFLAG - if set, then changes in localParameterBlock variables in the
* globalGraphics state made in the CVT preprogram are not copied back into
* the defaultParameterBlock. So, the original default values are the starting
* values for each glyph.
*
* stack: value, selector => -;
*
*/
FS_PRIVATE uint8* itrp_INSTCTRL (IPARAM) /* <13> */
{
fnt_GlobalGraphicStateType *globalGS;
int32 *ic;
int32 selector;
int32 value;
int32 arg;
FS_UNUSED_PARAMETER(lOpCode);
globalGS = LocalGS.globalGS;
ic = (int32*)&globalGS->localParBlock.instructControl;
arg = CHECK_POP (LocalGS.stackPointer);
value = CHECK_POP (LocalGS.stackPointer);
CHECK_INT16 (arg);
selector = (int32)arg;
CHECK_SELECTOR (selector);
if (globalGS->init)
{
if (selector == 1)
*ic &= ~NOGRIDFITFLAG;
else if (selector == 2)
*ic &= ~DEFAULTFLAG;
*ic |= value;
}
return pbyInst;
}
/*
* AdjustAngle <4>
*/
FS_PRIVATE uint8* itrp_AA (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
/* This is a NOP now. However, do pop the argument off the stack -amitc- 9/11/91. */
/* Discard the popped value. -lenox- 11/11/91 */
(void) CHECK_POP (LocalGS.stackPointer);
/* old code now lives in history.fnt - deanb */
return pbyInst;
}
/*********************************************************************/
/* Called by itrp_PUSHB and itrp_NPUSHB */
/* these functions were split out from itrp_PushSomeStuff - deanb */
FS_PRIVATE uint8* itrp_PushSomeBytes (GSP int32 count, uint8* pbyInst)
{
F26Dot6 *stack;
stack = LocalGS.stackPointer;
while (count != 0)
{
CHECK_PUSH (stack, *pbyInst++);
count--;
}
LocalGS.stackPointer = stack;
return pbyInst;
}
FS_PRIVATE uint8* itrp_PushSomeWords (GSP int32 count, uint8* pbyInst)
{
F26Dot6 *stack;
int16 word;
stack = LocalGS.stackPointer;
while (count != 0)
{
word = *pbyInst++;
CHECK_PUSH (stack, (int16) ((word << 8) + *pbyInst++));
count--;
}
LocalGS.stackPointer = stack;
return pbyInst;
}
/*********************************************************************/
/*
* PUSH 1 Byte the most commonly called pushb
*/
FS_PRIVATE uint8* itrp_PUSHB1 (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
CHECK_PUSH (LocalGS.stackPointer, *pbyInst++);
return pbyInst;
}
/*
* PUSH Bytes
*/
FS_PRIVATE uint8* itrp_PUSHB (IPARAM)
{
int32 iCount;
iCount = lOpCode - 0xb0 + 1;
return itrp_PushSomeBytes (GSA iCount, pbyInst);
}
/*
* N PUSH Bytes
*/
FS_PRIVATE uint8* itrp_NPUSHB (IPARAM)
{
int32 iCount;
FS_UNUSED_PARAMETER(lOpCode);
iCount = (int32)*pbyInst++;
return itrp_PushSomeBytes (GSA iCount, pbyInst);
}
/*
* PUSH 1 Word the most commonly called pushw
*/
FS_PRIVATE uint8* itrp_PUSHW1 (IPARAM)
{
int16 word;
FS_UNUSED_PARAMETER(lOpCode);
word = *pbyInst++;
CHECK_PUSH (LocalGS.stackPointer, (int16)((word << 8) + *pbyInst++));
return pbyInst;
}
/*
* PUSH Words <3>
*/
FS_PRIVATE uint8* itrp_PUSHW (IPARAM)
{
int32 iCount;
iCount = lOpCode - 0xb8 + 1;
return itrp_PushSomeWords (GSA iCount, pbyInst);
}
/*
* N PUSH Words
*/
FS_PRIVATE uint8* itrp_NPUSHW (IPARAM)
{
int32 iCount;
FS_UNUSED_PARAMETER(lOpCode);
iCount = (int32)*pbyInst++;
return itrp_PushSomeWords (GSA iCount, pbyInst);
}
/*********************************************************************/
/*
* Write Store
*/
FS_PRIVATE uint8* itrp_WS (IPARAM)
{
F26Dot6 storage;
int32 storeIndex;
FS_UNUSED_PARAMETER(lOpCode);
storage = CHECK_POP (LocalGS.stackPointer);
storeIndex = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_STORAGE (&LocalGS,storeIndex);
LocalGS.globalGS->store[ storeIndex ] = storage;
return pbyInst;
}
/*
* Read Store
*/
FS_PRIVATE uint8* itrp_RS (IPARAM)
{
int32 storeIndex;
FS_UNUSED_PARAMETER(lOpCode);
storeIndex = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_STORAGE (&LocalGS, storeIndex);
CHECK_PUSH (LocalGS.stackPointer, LocalGS.globalGS->store[storeIndex]);
return pbyInst;
}
/*
* Write Control Value Table from outLine, assumes the value comes form the outline domain
*/
FS_PRIVATE uint8* itrp_WCVT (IPARAM)
{
int32 cvtIndex;
F26Dot6 cvtValue;
FS_UNUSED_PARAMETER(lOpCode);
cvtValue = CHECK_POP (LocalGS.stackPointer);
cvtIndex = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_CVT (&LocalGS, cvtIndex);
if (cvtValue != 0 && LocalGS.GetCVTEntry != itrp_GetCVTEntryFast)
cvtValue = FixDiv (cvtValue, itrp_GetCVTScale (GSA0));
LocalGS.globalGS->controlValueTable[ cvtIndex ] = cvtValue;
return pbyInst;
}
/*
* Write Control Value Table From Original Domain, assumes the value comes from the original domain, not the cvt or outline
*/
FS_PRIVATE uint8* itrp_WCVTFOD (IPARAM)
{
int32 cvtIndex;
F26Dot6 cvtValue;
fnt_GlobalGraphicStateType *globalGS = LocalGS.globalGS;
FS_UNUSED_PARAMETER(lOpCode);
cvtValue = CHECK_POP (LocalGS.stackPointer);
cvtIndex = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_CVT (&LocalGS, cvtIndex);
globalGS->controlValueTable[ cvtIndex ] = globalGS->ScaleFuncCVT (&globalGS->scaleCVT, cvtValue);
return pbyInst;
}
/*
* Read Control Value Table
*/
FS_PRIVATE uint8* itrp_RCVT (IPARAM)
{
int32 cvtIndex;
FS_UNUSED_PARAMETER(lOpCode);
cvtIndex = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_CVT (&LocalGS, cvtIndex);
CHECK_PUSH (LocalGS.stackPointer, LocalGS.GetCVTEntry (GSA cvtIndex));
return pbyInst;
}
/*
* Read Coordinate
*/
FS_PRIVATE uint8* itrp_RC (IPARAM)
{
int32 pt;
fnt_ElementType * element;
F26Dot6 proj;
pt = (int32)CHECK_POP (LocalGS.stackPointer);
element = LocalGS.CE2;
CHECK_POINT (&LocalGS, element, pt);
if (BIT0 (lOpCode))
proj = (*LocalGS.OldProject) (GSA element->ox[pt], element->oy[pt]);
else
proj = (*LocalGS.Project) (GSA element->x[pt], element->y[pt]);
CHECK_PUSH (LocalGS.stackPointer, proj);
return pbyInst;
}
/*
* Write Coordinate
*/
FS_PRIVATE uint8* itrp_WC (IPARAM)
{
F26Dot6 proj, coord;
int32 pt;
fnt_ElementType *element;
FS_UNUSED_PARAMETER(lOpCode);
coord = CHECK_POP (LocalGS.stackPointer);/* value */
pt = (int32)CHECK_POP (LocalGS.stackPointer);/* point */
element = LocalGS.CE2;
CHECK_POINT (&LocalGS, element, pt);
proj = (*LocalGS.Project) (GSA element->x[pt], element->y[pt]);
proj = coord - proj;
(*LocalGS.MovePoint) (GSA element, pt, proj);
if (element == &LocalGS.elements[TWILIGHTZONE])
{
element->ox[pt] = element->x[pt];
element->oy[pt] = element->y[pt];
}
return pbyInst;
}
/*
* Measure Distance
*/
FS_PRIVATE uint8* itrp_MD (IPARAM)
{
int32 pt1, pt2;
F26Dot6 proj, *stack = LocalGS.stackPointer;
fnt_GlobalGraphicStateType *globalGS = LocalGS.globalGS;
pt2 = (int32)CHECK_POP (stack);
pt1 = (int32)CHECK_POP (stack);
CHECK_POINT (&LocalGS, LocalGS.CE0, pt2);
CHECK_POINT (&LocalGS, LocalGS.CE1, pt1);
if (BIT0 (lOpCode - MD_CODE))
proj = (*LocalGS.OldProject) (GSA LocalGS.CE0->ox[pt1] - LocalGS.CE1->ox[pt2], LocalGS.CE0->oy[pt1] - LocalGS.CE1->oy[pt2]);
else
proj = (*LocalGS.Project) (GSA LocalGS.CE0->x[pt1] - LocalGS.CE1->x[pt2], LocalGS.CE0->y[pt1] - LocalGS.CE1->y[pt2]);
CHECK_PUSH (stack, proj);
LocalGS.stackPointer = stack;
return pbyInst;
}
/*
* Measure Pixels Per EM
*/
FS_PRIVATE uint8* itrp_MPPEM (IPARAM)
{
uint16 ppem;
fnt_GlobalGraphicStateType *globalGS = LocalGS.globalGS;
FS_UNUSED_PARAMETER(lOpCode);
ppem = globalGS->pixelsPerEm;
if (!globalGS->bSameStretch)
ppem = (uint16)FixMul (ppem, itrp_GetCVTScale (GSA0));
CHECK_PUSH (LocalGS.stackPointer, ppem);
return pbyInst;
}
/*
* Measure Point Size
*/
FS_PRIVATE uint8* itrp_MPS (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
CHECK_PUSH (LocalGS.stackPointer, LocalGS.globalGS->pointSize);
return pbyInst;
}
/*
* Get Miscellaneous info: version number, rotated, stretched <6>
* Version number is 8 bits. This is version 0x01 : 5/1/90
*
*/
FS_PRIVATE uint8* itrp_GETINFO (IPARAM)
{
fnt_GlobalGraphicStateType *globalGS = LocalGS.globalGS;
int32 info = 0;
int32 selector;
int32 arg;
FS_UNUSED_PARAMETER(lOpCode);
arg = CHECK_POP (LocalGS.stackPointer);
CHECK_INT16 (arg);
selector = (int32)arg;
CHECK_SELECTOR (selector);
if (selector & 1) /* version */
info |= RASTERIZER_VERSION;
if ((selector & 2) && (globalGS->non90DegreeTransformation & NON90DEGTRANS_ROTATED))
info |= ROTATEDGLYPH;
if ((selector & 4) && (globalGS->non90DegreeTransformation & NON90DEGTRANS_STRETCH))
info |= STRETCHEDGLYPH;
CHECK_PUSH (LocalGS.stackPointer, info);
return pbyInst;
}
/*
* FLIP ON
*/
FS_PRIVATE uint8* itrp_FLIPON (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.globalGS->localParBlock.autoFlip = true;
return pbyInst;
}
/*
* FLIP OFF
*/
FS_PRIVATE uint8* itrp_FLIPOFF (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
LocalGS.globalGS->localParBlock.autoFlip = false;
return pbyInst;
}
#ifndef NOT_ON_THE_MAC
#ifdef FSCFG_DEBUG
/*
* DEBUG
*/
FS_PRIVATE uint8* itrp_DEBUG (IPARAM)
{
int32 arg;
int8 buffer[24];
FS_UNUSED_PARAMETER(lOpCode);
arg = CHECK_POP (LocalGS.stackPointer);
buffer[1] = 'D';
buffer[2] = 'E';
buffer[3] = 'B';
buffer[4] = 'U';
buffer[5] = 'G';
buffer[6] = ' ';
if (arg >= 0)
{
buffer[7] = '+';
}
else
{
arg = -arg;
buffer[7] = '-';
}
buffer[13] = arg % 10 + '0';
arg /= 10;
buffer[12] = arg % 10 + '0';
arg /= 10;
buffer[11] = arg % 10 + '0';
arg /= 10;
buffer[10] = arg % 10 + '0';
arg /= 10;
buffer[ 9] = arg % 10 + '0';
arg /= 10;
buffer[ 8] = arg % 10 + '0';
arg /= 10;
buffer[14] = arg ? '*' : ' ';
buffer[0] = 14; /* convert to pascal */
DEBUGSTR (buffer);
return pbyInst;
}
#else /* debug */
FS_PRIVATE uint8* itrp_DEBUG (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
CHECK_POP (LocalGS.stackPointer);
return pbyInst;
}
#endif /* debug */
#else
FS_PRIVATE uint8* itrp_DEBUG (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
CHECK_POP (LocalGS.stackPointer);
return pbyInst;
}
#endif /* ! not on the mac */
/* these functions were split out from itrp_BinaryOperand - deanb */
FS_PRIVATE uint8* itrp_LT (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
LocalGS.stackPointer = pfxStack;
pfxStack[-1] = (pfxStack[-1] < pfxStack[0]) ? 1 : 0;
CHECK_STACK (&LocalGS);
return pbyInst;
}
FS_PRIVATE uint8* itrp_LTEQ (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
LocalGS.stackPointer = pfxStack;
pfxStack[-1] = (pfxStack[-1] <= pfxStack[0]) ? 1 : 0;
CHECK_STACK (&LocalGS);
return pbyInst;
}
FS_PRIVATE uint8* itrp_GT (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
LocalGS.stackPointer = pfxStack;
pfxStack[-1] = (pfxStack[-1] > pfxStack[0]) ? 1 : 0;
CHECK_STACK (&LocalGS);
return pbyInst;
}
FS_PRIVATE uint8* itrp_GTEQ (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
LocalGS.stackPointer = pfxStack;
pfxStack[-1] = (pfxStack[-1] >= pfxStack[0]) ? 1 : 0;
CHECK_STACK (&LocalGS);
return pbyInst;
}
FS_PRIVATE uint8* itrp_EQ (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
LocalGS.stackPointer = pfxStack;
pfxStack[-1] = (pfxStack[-1] == pfxStack[0]) ? 1 : 0;
CHECK_STACK (&LocalGS);
return pbyInst;
}
FS_PRIVATE uint8* itrp_NEQ (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
LocalGS.stackPointer = pfxStack;
pfxStack[-1] = (pfxStack[-1] != pfxStack[0]) ? 1 : 0;
CHECK_STACK (&LocalGS);
return pbyInst;
}
FS_PRIVATE uint8* itrp_AND (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
LocalGS.stackPointer = pfxStack;
pfxStack[-1] = (pfxStack[-1] && pfxStack[0]) ? 1 : 0;
CHECK_STACK (&LocalGS);
return pbyInst;
}
FS_PRIVATE uint8* itrp_OR (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
LocalGS.stackPointer = pfxStack;
pfxStack[-1] = (pfxStack[-1] || pfxStack[0]) ? 1 : 0;
CHECK_STACK (&LocalGS);
return pbyInst;
}
FS_PRIVATE uint8* itrp_ADD (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
LocalGS.stackPointer = pfxStack;
pfxStack[-1] += pfxStack[0];
CHECK_STACK (&LocalGS);
return pbyInst;
}
FS_PRIVATE uint8* itrp_SUB (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
LocalGS.stackPointer = pfxStack;
pfxStack[-1] -= pfxStack[0];
CHECK_STACK (&LocalGS);
return pbyInst;
}
FS_PRIVATE uint8* itrp_MUL (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
LocalGS.stackPointer = pfxStack;
pfxStack[-1] = Mul26Dot6(pfxStack[-1], pfxStack[0]);
CHECK_STACK (&LocalGS);
return pbyInst;
}
FS_PRIVATE uint8* itrp_DIV (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
LocalGS.stackPointer = pfxStack;
pfxStack[-1] = (int32)(((long)pfxStack[-1] << 6) / pfxStack[0]);
CHECK_STACK (&LocalGS);
return pbyInst;
}
FS_PRIVATE uint8* itrp_MAX (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
LocalGS.stackPointer = pfxStack;
if (pfxStack[-1] < pfxStack[0])
{
pfxStack[-1] = pfxStack[0];
}
CHECK_STACK (&LocalGS);
return pbyInst;
}
FS_PRIVATE uint8* itrp_MIN (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
LocalGS.stackPointer = pfxStack;
if (pfxStack[-1] > pfxStack[0])
{
pfxStack[-1] = pfxStack[0];
}
CHECK_STACK (&LocalGS);
return pbyInst;
}
/**************************************************************************/
/* these functions were split out from itrp_UnaryOperand - deanb */
FS_PRIVATE uint8* itrp_ODD (IPARAM)
{
F26Dot6 *pfxStack;
F26Dot6 fxArg;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
fxArg = itrp_RoundToGrid (GSA *pfxStack, 0);
fxArg >>= FNT_PIXELSHIFT;
*pfxStack = fxArg & 1L;
return pbyInst;
}
FS_PRIVATE uint8* itrp_EVEN (IPARAM)
{
F26Dot6 *pfxStack;
F26Dot6 fxArg;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
fxArg = itrp_RoundToGrid (GSA *pfxStack, 0);
fxArg >>= FNT_PIXELSHIFT;
fxArg++;
*pfxStack = fxArg & 1L;
return pbyInst;
}
FS_PRIVATE uint8* itrp_NOT (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
*pfxStack = !*pfxStack;
return pbyInst;
}
FS_PRIVATE uint8* itrp_ABS (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
if (*pfxStack < 0L)
{
*pfxStack = -*pfxStack;
}
return pbyInst;
}
FS_PRIVATE uint8* itrp_NEG (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
*pfxStack = -*pfxStack;
return pbyInst;
}
FS_PRIVATE uint8* itrp_CEILING (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
*pfxStack += FNT_PIXELSIZE - 1;
*pfxStack &= ~(FNT_PIXELSIZE - 1);
return pbyInst;
}
FS_PRIVATE uint8* itrp_FLOOR (IPARAM)
{
F26Dot6 *pfxStack;
FS_UNUSED_PARAMETER(lOpCode);
pfxStack = LocalGS.stackPointer - 1;
*pfxStack &= ~(FNT_PIXELSIZE - 1);
return pbyInst;
}
/**************************************************************************/
/* This is called by itrp_IF, itrp_ELSE, itrp_FDEF, and itrp_IDEF */
/* It is used to find the next TrueType instruction in the instruction */
/* stream by skipping over push data. It is table driven for speed. */
static const uint8 gbyPushTable[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
21,22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 2, 3, 4, 5, 6, 7, 8, 2, 4, 6, 8,10,12,14,16,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
FS_PRIVATE uint8* itrp_SkipPushData (GSP uint8* pbyInst)
{
int32 iDataCount; /* count of data following push instruction */
iDataCount = (int32)gbyPushTable[ pbyInst[-1] ]; /* opcode */
if (iDataCount != 0) /* if a push instruction */
{
if (iDataCount == 21) /* special for npushb */
{
iDataCount = (int32)*pbyInst + 1;
}
else if (iDataCount == 22) /* special for npushw */
{
iDataCount = ((int32)*pbyInst << 1) + 1;
}
pbyInst += iDataCount;
}
return pbyInst;
}
/**************************************************************************/
/*
* IF
*/
FS_PRIVATE uint8* itrp_IF (IPARAM)
{
int32 iLevel;
int32 iScanOpCode;
int32 iDataCount; /* count of data following push instruction */
FS_UNUSED_PARAMETER(lOpCode);
if (!CHECK_POP (LocalGS.stackPointer))
{
iLevel = 1;
while (iLevel != 0) /* iLevel = # of IF's minus # of EIF's */
{
iScanOpCode = (int32)*pbyInst++;
if (iScanOpCode == EIF_CODE)
{
ERR_IF (-1);
iLevel--;
}
else if (iScanOpCode == IF_CODE)
{
ERR_IF (1);
iLevel++;
}
else if (iScanOpCode == ELSE_CODE)
{
if (iLevel == 1)
break;
}
else
{
iDataCount = (int32)gbyPushTable[iScanOpCode];
if (iDataCount != 0) /* if a push instruction */
{
if (iDataCount == 21) /* special for npushb */
{
iDataCount = (int32)*pbyInst + 1;
}
else if (iDataCount == 22) /* special for npushw */
{
iDataCount = ((int32)*pbyInst << 1) + 1;
}
pbyInst += iDataCount;
}
}
}
}
return pbyInst;
}
/**************************************************************************/
/*
* ELSE for the IF
*/
FS_PRIVATE uint8* itrp_ELSE (IPARAM)
{
int16 level;
uint8 opCode;
FS_UNUSED_PARAMETER(lOpCode);
for (level = 1; level;) /* level = # of "ifs" minus # of "endifs" */
{
opCode = *pbyInst++;
if (opCode == EIF_CODE)
{
ERR_IF (-1);
level--;
}
else if (opCode == IF_CODE)
{
ERR_IF (1);
level++;
}
else
{
pbyInst = itrp_SkipPushData (GSA pbyInst);
}
}
return pbyInst;
}
/**************************************************************************/
/*
* End IF
*/
FS_PRIVATE uint8* itrp_EIF (IPARAM)
{
FS_UNUSED_PARAMETER(lOpCode);
return pbyInst;
}
/**************************************************************************/
/*
* Jump Relative
*/
FS_PRIVATE uint8* itrp_JMPR (IPARAM)
{
int32 offset;
FS_UNUSED_PARAMETER(lOpCode);
offset = (int32)CHECK_POP (LocalGS.stackPointer);
offset--; /* since the interpreter post-increments the IP */
pbyInst += offset;
return pbyInst;
}
/**************************************************************************/
/*
* Jump Relative On True
*/
FS_PRIVATE uint8* itrp_JROT (IPARAM)
{
int32 offset;
boolean bFlag;
FS_UNUSED_PARAMETER(lOpCode);
bFlag = (boolean)CHECK_POP (LocalGS.stackPointer);
offset = (int32)CHECK_POP (LocalGS.stackPointer);
if (bFlag)
{
pbyInst += offset - 1; /* interpreter post-increments the IP */
}
return pbyInst;
}
/**************************************************************************/
/*
* Jump Relative On False
*/
FS_PRIVATE uint8* itrp_JROF (IPARAM)
{
int32 offset;
boolean bFlag;
FS_UNUSED_PARAMETER(lOpCode);
bFlag = (boolean)CHECK_POP (LocalGS.stackPointer);
offset = (int32)CHECK_POP (LocalGS.stackPointer);
if (!bFlag)
{
pbyInst += offset - 1; /* interpreter post-increments the IP */
}
return pbyInst;
}
/**************************************************************************/
/*
* ROUND
*/
FS_PRIVATE uint8* itrp_ROUND (IPARAM)
{
F26Dot6 arg1;
fnt_ParameterBlock *pb = &LocalGS.globalGS->localParBlock;
arg1 = CHECK_POP (LocalGS.stackPointer);
CHECK_RANGE (lOpCode, 0x68, 0x6B);
arg1 = pb->RoundValue (GSA arg1, LocalGS.globalGS->engine[lOpCode - 0x68]);
CHECK_PUSH (LocalGS.stackPointer , arg1);
return pbyInst;
}
/*
* No ROUND
*/
FS_PRIVATE uint8* itrp_NROUND (IPARAM)
{
F26Dot6 arg1;
arg1 = CHECK_POP (LocalGS.stackPointer);
CHECK_RANGE (lOpCode, 0x6C, 0x6F);
arg1 = itrp_RoundOff (GSA arg1, LocalGS.globalGS->engine[lOpCode - 0x6c]);
CHECK_PUSH (LocalGS.stackPointer , arg1);
return pbyInst;
}
/**************************************************************************/
/*
* An internal function used by MIRP an MDRP.
*/
F26Dot6 itrp_CheckSingleWidth (GSP F26Dot6 fxValue)
{
F26Dot6 fxDelta;
F26Dot6 fxScaledSW;
fnt_ParameterBlock *pb;
pb = &LocalGS.globalGS->localParBlock;
fxScaledSW = LocalGS.GetSingleWidth (GSA0);
if (fxValue >= 0)
{
fxDelta = fxValue - fxScaledSW;
if (fxDelta < 0)
fxDelta = -fxDelta;
if (fxDelta < pb->sWCI)
fxValue = fxScaledSW;
}
else
{
fxValue = -fxValue;
fxDelta = fxValue - fxScaledSW;
if (fxDelta < 0)
fxDelta = -fxDelta;
if (fxDelta < pb->sWCI)
fxValue = fxScaledSW;
fxValue = -fxValue;
}
return fxValue;
}
/**************************************************************************/
/*
* Move Direct Relative Point
*/
FS_PRIVATE uint8* itrp_MDRP (IPARAM)
{
int32 iPt0;
int32 iPt1;
fnt_ElementType *pCE0;
fnt_ElementType *pCE1;
fnt_GlobalGraphicStateType *globalGS;
fnt_ParameterBlock *pb;
F26Dot6 fxMoveDist;
F26Dot6 fxUnRounded;
F26Dot6 fxMin;
iPt0 = LocalGS.Pt0;
pCE0 = LocalGS.CE0;
pCE1 = LocalGS.CE1;
globalGS = LocalGS.globalGS;
pb = &globalGS->localParBlock;
iPt1 = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_POINT (&LocalGS, pCE0, iPt0);
CHECK_POINT (&LocalGS, pCE1, iPt1);
if (pCE0 == &LocalGS.elements[TWILIGHTZONE] || pCE1 == &LocalGS.elements[TWILIGHTZONE] || LocalGS.globalGS->bCompositeGlyph)
{
fxMoveDist = (*LocalGS.OldProject) (GSA pCE1->ox[iPt1] - pCE0->ox[iPt0], pCE1->oy[iPt1] - pCE0->oy[iPt0]);
}
else if (globalGS->bSameStretch)
{
fxMoveDist = (*LocalGS.OldProject) (GSA pCE1->oox[iPt1] - pCE0->oox[iPt0], pCE1->ooy[iPt1] - pCE0->ooy[iPt0] );
fxMoveDist = globalGS->ScaleFuncCVT( &globalGS->scaleCVT, fxMoveDist );
}
else
{
fxMoveDist = (*LocalGS.OldProject) (GSA
globalGS->ScaleFuncX (&globalGS->scaleX, pCE1->oox[iPt1] - pCE0->oox[iPt0]),
globalGS->ScaleFuncY (&globalGS->scaleY, pCE1->ooy[iPt1] - pCE0->ooy[iPt0]) );
}
if (pb->sWCI)
{
fxMoveDist = itrp_CheckSingleWidth (GSA fxMoveDist);
}
fxUnRounded = fxMoveDist;
if (BIT2 (lOpCode))
{
fxMoveDist = pb->RoundValue (GSA fxMoveDist, globalGS->engine[lOpCode & 0x03]);
}
else
{
fxMoveDist = itrp_RoundOff (GSA fxMoveDist, globalGS->engine[lOpCode & 0x03]);
}
if (BIT3 (lOpCode))
{
fxMin = pb->minimumDistance;
if (fxUnRounded >= 0)
{
if (fxMoveDist < fxMin)
{
fxMoveDist = fxMin;
}
}
else
{
fxMin = -fxMin;
if (fxMoveDist > fxMin)
{
fxMoveDist = fxMin;
}
}
}
fxMoveDist -= (*LocalGS.Project) (GSA pCE1->x[iPt1] - pCE0->x[iPt0], pCE1->y[iPt1] - pCE0->y[iPt0]);
(*LocalGS.MovePoint) (GSA pCE1, iPt1, fxMoveDist);
LocalGS.Pt1 = iPt0;
LocalGS.Pt2 = iPt1;
if (BIT4 (lOpCode))
{
LocalGS.Pt0 = iPt1; /* move the reference point */
}
return pbyInst;
}
/**************************************************************************/
/*
* Move Indirect Relative Point General
*/
/*
* This routine branches to either the general MIRPG, or to the fast MIRPX
* or MIRPY. The MIRPCode is set to MIRPX at the beginning of each glyph,
* and may be changed to MIRPY or to MIRPX by the SVTCA instructions.
* Any other change in relevant state will cause the function vector to fall
* back to MIRPG.
*
* Conditions for fast MIRPX and MIRPY:
* fast cvt (identity transform)
* no single width cut in
* no twilight zone
* round to grid
* no engine compensation
* LocalGS.MovePoint = itrp_X[or Y]MovePoint;
*/
FS_PRIVATE uint8* itrp_MIRP (IPARAM)
{
int32 iPoint;
int32 iPt0;
int32 iCVTIndex;
F26Dot6 fxMoveDist;
F26Dot6 fxDif;
F26Dot6 fxMin;
F26Dot6 fxOutlineDist;
F26Dot6 fxPosition;
F26Dot6 fxEngine;
fnt_ParameterBlock *pb;
fnt_ElementType *pCE0;
fnt_ElementType *pCE1;
fnt_GlobalGraphicStateType *globalGS;
globalGS = LocalGS.globalGS; /* common setup */
pb = &globalGS->localParBlock;
pCE0 = LocalGS.CE0;
pCE1 = LocalGS.CE1;
iCVTIndex = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_CVT (&LocalGS, iCVTIndex);
iPoint = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_POINT (&LocalGS, LocalGS.CE1, iPoint);
iPt0 = LocalGS.Pt0;
LocalGS.Pt1 = iPt0;
LocalGS.Pt2 = iPoint;
if (LocalGS.MIRPCode == MIRPG) /********* MIRPG *********/
{
fxMoveDist = LocalGS.GetCVTEntry (GSA iCVTIndex);
if (pb->sWCI)
{
fxMoveDist = itrp_CheckSingleWidth (GSA fxMoveDist);
}
if (pCE1 == &LocalGS.elements[TWILIGHTZONE])
{
pCE1->ox[iPoint] = pCE0->ox[iPt0] + (F26Dot6) VECTORMUL (fxMoveDist, LocalGS.proj.x);
pCE1->x[iPoint] = pCE1->ox[iPoint];
pCE1->oy[iPoint] = pCE0->oy[iPt0] + (F26Dot6) VECTORMUL (fxMoveDist, LocalGS.proj.y);
pCE1->y[iPoint] = pCE1->oy[iPoint];
}
if (LocalGS.OldProject == itrp_XProject)
{
fxOutlineDist = pCE1->ox[iPoint] - pCE0->ox[iPt0];
}
else if (LocalGS.OldProject == itrp_YProject)
{
fxOutlineDist = pCE1->oy[iPoint] - pCE0->oy[iPt0];
}
else
{
fxOutlineDist = (*LocalGS.OldProject) (GSA pCE1->ox[iPoint] - pCE0->ox[iPt0], pCE1->oy[iPoint] - pCE0->oy[iPt0]);
}
if (((fxOutlineDist ^ fxMoveDist) < 0) && (pb->autoFlip))
{
fxMoveDist = -fxMoveDist; /* Do the auto flip */
}
fxEngine = globalGS->engine[lOpCode & 0x03];
if (BIT2 (lOpCode))
{
fxDif = fxMoveDist - fxOutlineDist;
if ((fxDif > pb->wTCI) || (fxDif < -pb->wTCI))
{
fxMoveDist = fxOutlineDist;
}
fxMoveDist = pb->RoundValue (GSA fxMoveDist, fxEngine);
}
else
{
fxMoveDist = itrp_RoundOff (GSA fxMoveDist, fxEngine);
}
if (BIT3 (lOpCode))
{
fxMin = pb->minimumDistance;
if (fxOutlineDist >= 0)
{
if (fxMoveDist < fxMin)
fxMoveDist = fxMin;
}
else
{
fxMin = -fxMin;
if (fxMoveDist > fxMin)
fxMoveDist = fxMin;
}
}
if (LocalGS.Project == itrp_XProject)
{
fxPosition = pCE1->x[iPoint] - pCE0->x[iPt0];
}
else if (LocalGS.Project == itrp_YProject)
{
fxPosition = pCE1->y[iPoint] - pCE0->y[iPt0];
}
else
{
fxPosition = (*LocalGS.Project) (GSA pCE1->x[iPoint] - pCE0->x[iPt0], pCE1->y[iPoint] - pCE0->y[iPt0]);
}
(*LocalGS.MovePoint) (GSA pCE1, iPoint, fxMoveDist - fxPosition);
}
else if (LocalGS.MIRPCode == MIRPX) /********* MIRPX *********/
{
fxMoveDist = globalGS->controlValueTable[ iCVTIndex ]; /* always fast */
fxOutlineDist = pCE1->ox[iPoint] - pCE0->ox[iPt0]; /* x direction only */
if (((fxOutlineDist ^ fxMoveDist) < 0) && (pb->autoFlip))
{
fxMoveDist = -fxMoveDist; /* Do the auto flip */
}
if (BIT2 (lOpCode))
{
fxDif = fxMoveDist - fxOutlineDist;
if ((fxDif > pb->wTCI) || (fxDif < -pb->wTCI))
{
fxMoveDist = fxOutlineDist;
}
if (fxMoveDist >= 0) /* round to grid in line */
{
fxMoveDist += FNT_PIXELSIZE / 2;
fxMoveDist &= ~ (FNT_PIXELSIZE - 1);
}
else
{
fxMoveDist = -fxMoveDist;
fxMoveDist += FNT_PIXELSIZE / 2;
fxMoveDist &= ~ (FNT_PIXELSIZE - 1);
fxMoveDist = -fxMoveDist;
}
} /* round off disappears */
if (BIT3 (lOpCode))
{
fxMin = pb->minimumDistance;
if (fxOutlineDist >= 0)
{
if (fxMoveDist < fxMin)
fxMoveDist = fxMin;
}
else
{
fxMin = -fxMin;
if (fxMoveDist > fxMin)
fxMoveDist = fxMin;
}
}
pCE1->x[iPoint] = fxMoveDist + pCE0->x[iPt0]; /* move point fast */
pCE1->f[iPoint] |= XMOVED;
}
else /* if (LocalGS.MIRPCode == MIRPY) */ /********* MIRPY *********/
{
fxMoveDist = globalGS->controlValueTable[ iCVTIndex ]; /* always fast */
fxOutlineDist = pCE1->oy[iPoint] - pCE0->oy[iPt0]; /* y direction only */
if (((fxOutlineDist ^ fxMoveDist) < 0) && (pb->autoFlip))
{
fxMoveDist = -fxMoveDist; /* Do the auto flip */
}
if (BIT2 (lOpCode))
{
fxDif = fxMoveDist - fxOutlineDist;
if ((fxDif > pb->wTCI) || (fxDif < -pb->wTCI))
{
fxMoveDist = fxOutlineDist;
}
if (fxMoveDist >= 0) /* round to grid in line */
{
fxMoveDist += FNT_PIXELSIZE / 2;
fxMoveDist &= ~ (FNT_PIXELSIZE - 1);
}
else
{
fxMoveDist = -fxMoveDist;
fxMoveDist += FNT_PIXELSIZE / 2;
fxMoveDist &= ~ (FNT_PIXELSIZE - 1);
fxMoveDist = -fxMoveDist;
}
} /* round off disappears */
if (BIT3 (lOpCode))
{
fxMin = pb->minimumDistance;
if (fxOutlineDist >= 0)
{
if (fxMoveDist < fxMin)
fxMoveDist = fxMin;
}
else
{
fxMin = -fxMin;
if (fxMoveDist > fxMin)
fxMoveDist = fxMin;
}
}
pCE1->y[iPoint] = fxMoveDist + pCE0->y[iPt0]; /* move point fast */
pCE1->f[iPoint] |= YMOVED;
}
if (BIT4 (lOpCode))
{
LocalGS.Pt0 = iPoint; /* move the reference point */
}
return pbyInst;
}
/**************************************************************************/
/*
* CALL a function
*/
FS_PRIVATE uint8* itrp_CALL (IPARAM)
{
fnt_funcDef *funcDef;
uint8 *pbySubroutine;
fnt_GlobalGraphicStateType *globalGS;
int32 arg;
uint8 *pbyEndInst; /* saves parent's stop condition */
FS_UNUSED_PARAMETER(lOpCode);
globalGS = LocalGS.globalGS;
arg = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_PROGRAM (funcDef->pgmIndex);
CHECK_FDEF (&LocalGS, arg);
funcDef = &globalGS->funcDef[ arg ];
pbySubroutine = globalGS->pgmList[ funcDef->pgmIndex ].Instruction;
CHECK_ASSERTION (globalGS->funcDef != 0);
CHECK_ASSERTION (pbySubroutine != 0);
pbySubroutine += funcDef->start;
pbyEndInst = LocalGS.pbyEndInst; /* save for parent */
LocalGS.Interpreter (GSA pbySubroutine, pbySubroutine + funcDef->length); /* recursion */
LocalGS.pbyEndInst = pbyEndInst; /* restore for parent */
if (LocalGS.ercReturn != NO_ERR) /* if illegal inst has been hit */
{
return pbyEndInst; /* exit parent's loop */
}
return pbyInst;
}
/**************************************************************************/
/*
* Function DEFinition
*/
FS_PRIVATE uint8* itrp_FDEF (IPARAM)
{
fnt_funcDef *funcDef;
uint8 * program, *funcStart;
fnt_GlobalGraphicStateType * globalGS;
int32 arg;
FS_UNUSED_PARAMETER(lOpCode);
globalGS = LocalGS.globalGS;
arg = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_FDEF (&LocalGS, arg);
funcDef = &globalGS->funcDef[ arg ];
program = globalGS->pgmList[ funcDef->pgmIndex = globalGS->pgmIndex ].Instruction;
CHECK_PROGRAM (funcDef->pgmIndex);
CHECK_ASSERTION (globalGS->funcDef != 0);
CHECK_ASSERTION (globalGS->pgmList[funcDef->pgmIndex].Instruction != 0);
funcDef->start = pbyInst - program;
funcStart = pbyInst;
while ((*pbyInst++) != ENDF_CODE)
{
pbyInst = itrp_SkipPushData (GSA pbyInst);
}
funcDef->length = (uint16)(pbyInst - funcStart - 1); /* don't execute ENDF */
return pbyInst;
}
/**************************************************************************/
/*
* LOOP while CALLing a function
*/
FS_PRIVATE uint8* itrp_LOOPCALL (IPARAM)
{
uint8 *start, *stop;
InterpreterFunc Interpreter;
fnt_funcDef *funcDef;
int32 arg;
int32 loop;
uint8 * ins;
uint8 *pbyEndInst; /* saves parent's stop condition */
FS_UNUSED_PARAMETER(lOpCode);
arg = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_FDEF (&LocalGS, arg);
funcDef = & (LocalGS.globalGS->funcDef[ arg ]);
{
CHECK_PROGRAM (funcDef->pgmIndex);
ins = LocalGS.globalGS->pgmList[ funcDef->pgmIndex ].Instruction;
start = &ins[funcDef->start];
stop = &ins[funcDef->start + funcDef->length]; /* funcDef->end -> funcDef->length <4> */
}
Interpreter = LocalGS.Interpreter;
arg = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_INT16 (arg);
CHECK_LARGER (-1L, arg);
loop = (int32)arg;
pbyEndInst = LocalGS.pbyEndInst; /* save for parent */
for (--loop; ((loop >= 0) && (LocalGS.ercReturn == NO_ERR)); --loop)
{
Interpreter (GSA start, stop);
}
LocalGS.pbyEndInst = pbyEndInst; /* restore for parent */
if (LocalGS.ercReturn != NO_ERR) /* if illegal inst has been hit */
{
return pbyEndInst; /* exit parent's loop */
}
return pbyInst;
}
/**************************************************************************/
/*
* This guy returns the index of the given opCode, or 0 if not found <4>
*/
FS_PRIVATE fnt_instrDef *itrp_FindIDef (GSP uint8 opCode)
{
fnt_GlobalGraphicStateType *globalGS;
int32 count;
fnt_instrDef*instrDef;
globalGS = LocalGS.globalGS;
count = globalGS->instrDefCount;
instrDef = globalGS->instrDef;
for (--count; count >= 0; instrDef++, --count)
{
if (instrDef->opCode == opCode)
{
return instrDef;
}
}
return 0;
}
/**************************************************************************/
/*
* This guy gets called for opCodes that has been patch by the font's IDEF <4>
* or if they have never been defined. If there is no corresponding IDEF,
* flag it as an illegal instruction.
*/
FS_PRIVATE uint8* itrp_IDefPatch (IPARAM)
{
fnt_instrDef *instrDef;
uint8 *program;
uint8 *pbyEndInst; /* saves parent's stop condition */
pbyEndInst = LocalGS.pbyEndInst; /* save for parent */
instrDef = itrp_FindIDef (GSA (uint8)lOpCode);
if (instrDef == 0)
{
return itrp_IllegalInstruction (GSA pbyInst, lOpCode);
}
else
{
CHECK_PROGRAM (instrDef->pgmIndex);
program = LocalGS.globalGS->pgmList[ instrDef->pgmIndex ].Instruction;
program += instrDef->start;
LocalGS.Interpreter (GSA program, program + instrDef->length);
LocalGS.pbyEndInst = pbyEndInst; /* restore for parent */
if (LocalGS.ercReturn != NO_ERR) /* if illegal inst has been hit */
{
return pbyEndInst; /* exit parent's loop */
}
}
return pbyInst;
}
/**************************************************************************/
/*
* Instruction DEFinition <4>
*/
FS_PRIVATE uint8* itrp_IDEF (IPARAM)
{
int32 arg;
uint8 opCode;
fnt_instrDef *instrDef;
int32 pgmIndex;
uint8 * program;
uint8 * instrStart;
FS_UNUSED_PARAMETER(lOpCode);
pgmIndex = (int32)LocalGS.globalGS->pgmIndex;
program = LocalGS.globalGS->pgmList[ pgmIndex ].Instruction;
instrStart = pbyInst;
arg = CHECK_POP (LocalGS.stackPointer);
CHECK_INT8 (arg);
opCode = (uint8)arg;
CHECK_PROGRAM (pgmIndex);
instrDef = itrp_FindIDef (GSA opCode);
if (!instrDef)
{
instrDef = LocalGS.globalGS->instrDef + LocalGS.globalGS->instrDefCount++;
}
instrDef->pgmIndex = (uint8) pgmIndex;
instrDef->opCode = opCode; /* this may or may not have been set */
instrDef->start = pbyInst - program;
while (*pbyInst++ != ENDF_CODE)
{
pbyInst = itrp_SkipPushData (GSA pbyInst);
}
instrDef->length = (uint16)(pbyInst - instrStart - 1); /* don't execute ENDF */
return pbyInst;
}
/**************************************************************************/
/*
* UnTouch Point
*/
FS_PRIVATE uint8* itrp_UTP (IPARAM)
{
uint8*f = LocalGS.CE0->f;
int32 point;
FS_UNUSED_PARAMETER(lOpCode);
point = (int32)CHECK_POP (LocalGS.stackPointer);
CHECK_POINT (&LocalGS, LocalGS.CE0, point);
if (LocalGS.free.x)
{
f[point] &= ~XMOVED;
}
if (LocalGS.free.y)
{
f[point] &= ~YMOVED;
}
return pbyInst;
}
/*
* Set Delta Base
*/
FS_PRIVATE uint8* itrp_SDB (IPARAM)
{
int32 arg;
FS_UNUSED_PARAMETER(lOpCode);
arg = CHECK_POP (LocalGS.stackPointer);
CHECK_INT16 (arg);
LocalGS.globalGS->localParBlock.deltaBase = (int16)arg;
return pbyInst;
}
/*
* Set Delta Shift
*/
FS_PRIVATE uint8* itrp_SDS (IPARAM)
{
int32 arg;
FS_UNUSED_PARAMETER(lOpCode);
arg = CHECK_POP (LocalGS.stackPointer);
CHECK_INT16 (arg);
LocalGS.globalGS->localParBlock.deltaShift = (int16)arg;
return pbyInst;
}
/**************************************************************************/
/*
* DeltaEngine, internal support routine
*/
FS_PRIVATE void itrp_DeltaEngine (GSP FntMoveFunc doIt, int16 sBase, int16 sShift)
{
int32 iRange;
int32 iAim;
int32 iHigh;
int32 iFakePPEM;
int32 iPPEM;
F26Dot6 fxDelta;
/* Find the beginning of data pairs for this particular size */
iHigh = CHECK_POP (LocalGS.stackPointer) << 1;
LocalGS.stackPointer -= iHigh; /* -= number of pops required */
CHECK_STACK (&LocalGS);
iRange = LocalGS.globalGS->pixelsPerEm; /* same as itrp_MPPEM () */
if (!LocalGS.globalGS->bSameStretch)
{
iRange = (int32)FixMul(iRange, itrp_GetCVTScale (GSA0));
}
iFakePPEM = iRange - (int32)sBase;
if ((iFakePPEM >= 16) || (iFakePPEM < 0))
{
return; /* Not within exception range */
}
iFakePPEM = iFakePPEM << 4;
iAim = 0;
iRange = iHigh >> 1;
iRange &= ~1;
while (iRange > 2) /* binary search for first data */
{
iPPEM = LocalGS.stackPointer[ iAim + iRange ]; /* [ iPPEM << 4 | exception ] */
if ((iPPEM & ~0x0f) < iFakePPEM)
{
iAim += iRange; /* approach the starting point */
}
iRange >>= 1;
iRange &= ~1; /* iRange must stay even */
}
while (iAim < iHigh)
{
iPPEM = LocalGS.stackPointer[ iAim ]; /* [ iPPEM << 4 | exception ] */
fxDelta = iPPEM & ~0x0f;
if (fxDelta == iFakePPEM)
{ /* We found an exception, go ahead and apply it */
fxDelta = iPPEM & 0xf; /* 0 ... 15 */
fxDelta -= fxDelta >= 8 ? 7 : 8; /* -8 ... -1, 1 ... 8 */
fxDelta <<= FNT_PIXELSHIFT; /* convert to pixels */
fxDelta >>= sShift; /* scale to right size */
doIt (GSA LocalGS.CE0, (int32)LocalGS.stackPointer[iAim+1], (F26Dot6) fxDelta);
}
else if (fxDelta > iFakePPEM)
{
break; /* we passed the data */
}
iAim += 2;
}
}
/**************************************************************************/
/*
* DELTAP1
*/
FS_PRIVATE uint8* itrp_DELTAP1 (IPARAM)
{
fnt_ParameterBlock *pb;
FS_UNUSED_PARAMETER(lOpCode);
pb = &LocalGS.globalGS->localParBlock;
itrp_DeltaEngine (GSA LocalGS.MovePoint, pb->deltaBase, pb->deltaShift);
return pbyInst;
}
/*
* DELTAP2
*/
FS_PRIVATE uint8* itrp_DELTAP2 (IPARAM)
{
fnt_ParameterBlock *pb;
int16 sBase;
FS_UNUSED_PARAMETER(lOpCode);
pb = &LocalGS.globalGS->localParBlock;
sBase = (int16)(pb->deltaBase + 16);
itrp_DeltaEngine (GSA LocalGS.MovePoint, sBase, pb->deltaShift);
return pbyInst;
}
/*
* DELTAP3
*/
FS_PRIVATE uint8* itrp_DELTAP3 (IPARAM)
{
fnt_ParameterBlock *pb;
int16 sBase;
FS_UNUSED_PARAMETER(lOpCode);
pb = &LocalGS.globalGS->localParBlock;
sBase = (int16)(pb->deltaBase + 32);
itrp_DeltaEngine (GSA LocalGS.MovePoint, sBase, pb->deltaShift);
return pbyInst;
}
/*
* DELTAC1
*/
FS_PRIVATE uint8* itrp_DELTAC1 (IPARAM)
{
fnt_ParameterBlock *pb;
FS_UNUSED_PARAMETER(lOpCode);
pb = &LocalGS.globalGS->localParBlock;
itrp_DeltaEngine (GSA LocalGS.ChangeCvt, pb->deltaBase, pb->deltaShift);
return pbyInst;
}
/*
* DELTAC2
*/
FS_PRIVATE uint8* itrp_DELTAC2 (IPARAM)
{
fnt_ParameterBlock *pb;
int16 sBase;
FS_UNUSED_PARAMETER(lOpCode);
pb = &LocalGS.globalGS->localParBlock;
sBase = (int16)(pb->deltaBase + 16);
itrp_DeltaEngine (GSA LocalGS.ChangeCvt, sBase, pb->deltaShift);
return pbyInst;
}
/*
* DELTAC3
*/
FS_PRIVATE uint8* itrp_DELTAC3 (IPARAM)
{
fnt_ParameterBlock *pb;
int16 sBase;
FS_UNUSED_PARAMETER(lOpCode);
pb = &LocalGS.globalGS->localParBlock;
sBase = (int16)(pb->deltaBase + 32);
itrp_DeltaEngine (GSA LocalGS.ChangeCvt, sBase, pb->deltaShift);
return pbyInst;
}
#ifdef FSCFG_NO_INITIALIZED_DATA
void itrp_InitializeData (void)
{
int32 i;
/***** 0x00 - 0x0f *****/
function[0x00] = itrp_SVTCA_0;
function[0x01] = itrp_SVTCA_1;
function[0x02] = itrp_SPVTCA_0;
function[0x03] = itrp_SPVTCA_1;
function[0x04] = itrp_SFVTCA_0;
function[0x05] = itrp_SFVTCA_1;
function[0x06] = itrp_SPVTL;
function[0x07] = itrp_SPVTL;
function[0x08] = itrp_SFVTL;
function[0x09] = itrp_SFVTL;
function[0x0A] = itrp_WPV;
function[0x0B] = itrp_WFV;
function[0x0C] = itrp_RPV;
function[0x0D] = itrp_RFV;
function[0x0E] = itrp_SFVTPV;
function[0x0F] = itrp_ISECT;
/***** 0x10 - 0x1f *****/
function[0x10] = itrp_SRP0;
function[0x11] = itrp_SRP1;
function[0x12] = itrp_SRP2;
function[0x13] = itrp_SetElementPtr;
function[0x14] = itrp_SetElementPtr;
function[0x15] = itrp_SetElementPtr;
function[0x16] = itrp_SetElementPtr;
function[0x17] = itrp_LLOOP;
function[0x18] = itrp_RTG;
function[0x19] = itrp_RTHG;
function[0x1A] = itrp_LMD;
function[0x1B] = itrp_ELSE;
function[0x1C] = itrp_JMPR;
function[0x1D] = itrp_LWTCI;
function[0x1E] = itrp_LSWCI;
function[0x1F] = itrp_LSW;
/***** 0x20 - 0x2f *****/
function[0x20] = itrp_DUP;
function[0x21] = itrp_POP;
function[0x22] = itrp_CLEAR;
function[0x23] = itrp_SWAP;
function[0x24] = itrp_DEPTH;
function[0x25] = itrp_CINDEX;
function[0x26] = itrp_MINDEX;
function[0x27] = itrp_ALIGNPTS;
function[0x28] = itrp_RAW;
function[0x29] = itrp_UTP;
function[0x2A] = itrp_LOOPCALL;
function[0x2B] = itrp_CALL;
function[0x2C] = itrp_FDEF;
function[0x2D] = itrp_IllegalInstruction;
function[0x2E] = itrp_MDAP;
function[0x2F] = itrp_MDAP;
/***** 0x30 - 0x3f *****/
function[0x30] = itrp_IUP;
function[0x31] = itrp_IUP;
function[0x32] = itrp_SHP;
function[0x33] = itrp_SHP;
function[0x34] = itrp_SHC;
function[0x35] = itrp_SHC;
function[0x36] = itrp_SHE;
function[0x37] = itrp_SHE;
function[0x38] = itrp_SHPIX;
function[0x39] = itrp_IP;
function[0x3A] = itrp_MSIRP;
function[0x3B] = itrp_MSIRP;
function[0x3C] = itrp_ALIGNRP;
function[0x3D] = itrp_RTDG;
function[0x3E] = itrp_MIAP;
function[0x3F] = itrp_MIAP;
/***** 0x40 - 0x4f *****/
function[0x40] = itrp_NPUSHB;
function[0x41] = itrp_NPUSHW;
function[0x42] = itrp_WS;
function[0x43] = itrp_RS;
function[0x44] = itrp_WCVT;
function[0x45] = itrp_RCVT;
function[0x46] = itrp_RC;
function[0x47] = itrp_RC;
function[0x48] = itrp_WC;
function[0x49] = itrp_MD;
function[0x4A] = itrp_MD;
function[0x4B] = itrp_MPPEM;
function[0x4C] = itrp_MPS;
function[0x4D] = itrp_FLIPON;
function[0x4E] = itrp_FLIPOFF;
function[0x4F] = itrp_DEBUG;
/***** 0x50 - 0x5f *****/
function[0x50] = itrp_LT;
function[0x51] = itrp_LTEQ;
function[0x52] = itrp_GT;
function[0x53] = itrp_GTEQ;
function[0x54] = itrp_EQ;
function[0x55] = itrp_NEQ;
function[0x56] = itrp_ODD;
function[0x57] = itrp_EVEN;
function[0x58] = itrp_IF;
function[0x59] = itrp_EIF;
function[0x5A] = itrp_AND;
function[0x5B] = itrp_OR;
function[0x5C] = itrp_NOT;
function[0x5D] = itrp_DELTAP1;
function[0x5E] = itrp_SDB;
function[0x5F] = itrp_SDS;
/***** 0x60 - 0x6f *****/
function[0x60] = itrp_ADD;
function[0x61] = itrp_SUB;
function[0x62] = itrp_DIV;
function[0x63] = itrp_MUL;
function[0x64] = itrp_ABS;
function[0x65] = itrp_NEG;
function[0x66] = itrp_FLOOR;
function[0x67] = itrp_CEILING;
function[0x68] = itrp_ROUND;
function[0x69] = itrp_ROUND;
function[0x6A] = itrp_ROUND;
function[0x6B] = itrp_ROUND;
function[0x6C] = itrp_NROUND;
function[0x6D] = itrp_NROUND;
function[0x6E] = itrp_NROUND;
function[0x6F] = itrp_NROUND;
/***** 0x70 - 0x7f *****/
function[0x70] = itrp_WCVTFOD;
function[0x71] = itrp_DELTAP2;
function[0x72] = itrp_DELTAP3;
function[0x73] = itrp_DELTAC1;
function[0x74] = itrp_DELTAC2;
function[0x75] = itrp_DELTAC3;
function[0x76] = itrp_SROUND;
function[0x77] = itrp_S45ROUND;
function[0x78] = itrp_JROT;
function[0x79] = itrp_JROF;
function[0x7A] = itrp_ROFF;
function[0x7B] = itrp_IllegalInstruction;
function[0x7C] = itrp_RUTG;
function[0x7D] = itrp_RDTG;
function[0x7E] = itrp_SANGW;
function[0x7F] = itrp_AA;
/***** 0x80 - 0x8d *****/
function[0x80] = itrp_FLIPPT;
function[0x81] = itrp_FLIPRGON;
function[0x82] = itrp_FLIPRGOFF;
function[0x83] = itrp_IDefPatch;
function[0x84] = itrp_IDefPatch;
function[0x85] = itrp_SCANCTRL;
function[0x86] = itrp_SDPVTL;
function[0x87] = itrp_SDPVTL;
function[0x88] = itrp_GETINFO;
function[0x89] = itrp_IDEF;
function[0x8A] = itrp_ROTATE;
function[0x8B] = itrp_MAX;
function[0x8C] = itrp_MIN;
function[0x8D] = itrp_SCANTYPE;
function[0x8E] = itrp_INSTCTRL;
/***** 0x8f - 0xaf *****/
for ( i = 0x8F; i <= 0xAF; ++i )
function[i] = itrp_IDefPatch;
/***** 0xb0 - 0xb7 *****/
function[0xB0] = itrp_PUSHB1;
function[0xB1] = itrp_PUSHB;
function[0xB2] = itrp_PUSHB;
function[0xB3] = itrp_PUSHB;
function[0xB4] = itrp_PUSHB;
function[0xB5] = itrp_PUSHB;
function[0xB6] = itrp_PUSHB;
function[0xB7] = itrp_PUSHB;
/***** 0xb8 - 0xbf *****/
function[0xB8] = itrp_PUSHW1;
function[0xB9] = itrp_PUSHW;
function[0xBA] = itrp_PUSHW;
function[0xBB] = itrp_PUSHW;
function[0xBC] = itrp_PUSHW;
function[0xBD] = itrp_PUSHW;
function[0xBE] = itrp_PUSHW;
function[0xBF] = itrp_PUSHW;
/***** 0xc0 - 0xdf *****/
for ( i = 0xC0; i <= 0xDF; i++ )
function[i] = itrp_MDRP;
/***** 0xe0 - 0xff *****/
for ( i = 0xE0; i <= 0xFF; i++ )
function[i] = itrp_MIRP;
}
#endif /* FSCFG_NO_INITIALIZED_DATA */
/* END OF interp.c */