mirror of https://github.com/lianthony/NT4.0
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
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 */
|