-- JaMGraphicsImpl.mesa
-- Mesa 6 version
-- Last changed by Doug Wyatt, April 10, 1981 10:40 AM

DIRECTORY
JaMGraphicsDefs,
Graphics,
OpaqueDevice USING [],
Device USING [Handle, Object],
AltoDevice USING [Bitmap,NewAltoDevice, ScreenBitmap, ScreenOrigin],
PressDefs,
PressDevice USING [NewPressDevice,DumpScreen],
PressDeviceImpl,
Vector USING [Vec, Matrix, Sub, Add, Cross, Min, Max],
Cubic USING [Coeffs, Bezier, CoeffsToBezier, BezierToCoeffs,SetEpsilon],
SplineDefs USING [InitSplines, FPCoords, X, Y, Coeffs, SplineType,
MakeSpline, FreeCoeffs],
SplineMemoryDefs USING [Allocate, Free],
BcplFontFileDefs USING [OpenSDFontFile, CloseSDFontFile,
SplineCommandPtr, SplineDataPtr, GetSplineCommands],
JaMFnsDefs USING [PopInteger,PushInteger, PushReal, GetReal, PopString, PushString,
PushBoolean, Register, SetMouseProc, JaMStream],
KeyDefs USING [Mouse],
SystemDefs USING [AllocateHeapNode, FreeHeapNode];

JaMGraphicsImpl: PROGRAM
IMPORTS JaMFnsDefs,Graphics,AltoDevice,PressDevice, PressDefs, PressDeviceImpl,Vector,Cubic,
SplineDefs,SplineMemoryDefs,BcplFontFileDefs,SystemDefs
EXPORTS JaMGraphicsDefs, OpaqueDevice
SHARES PressDeviceImpl = {
OPEN JaMFnsDefs,Graphics;

DeviceObject: PUBLIC TYPE = Device.Object; -- exported into OpaqueDevice

Vec: TYPE = Vector.Vec;
Coeffs: TYPE = Cubic.Coeffs;
dev: DeviceContext←NIL;
pressdev: Device.Handle←NIL;
olddc: DisplayContext←NIL;
mousedc: DisplayContext←NIL;
dc: DisplayContext←NIL;

GetDC: PUBLIC PROCEDURE RETURNS[DisplayContext] = {
RETURN[dc];
};

InitDC: PROCEDURE = {
InitContext[dc];
};

PushDC: PROCEDURE = {
PushContext[dc];
};

PushBaseDC: PROCEDURE = {
PushBaseContext[dc];
};

PopDC: PROCEDURE = {
PopContext[dc];
};

Point: TYPE = Graphics.Vec;

GetPoint: PROCEDURE[p: POINTER TO Point] = {
p.y ← GetReal[];
p.x ← GetReal[];
};

PutPoint: PROCEDURE[p: POINTER TO Point] = {
PushReal[p.x];
PushReal[p.y];
};

Rect: TYPE = RECORD[ll,ur: Point];

GetRect: PROCEDURE[r: POINTER TO Rect] = {
GetPoint[@r.ur];
GetPoint[@r.ll];
};

PutRect: PROCEDURE[r: POINTER TO Rect] = {
PutPoint[@r.ll];
PutPoint[@r.ur];
};

JSetVw: PROCEDURE = {
rf: Rect;
rt: Rect;
GetRect[@rt];
GetRect[@rf];
-- *** fix this
-- SetView[dc,@rf,@rt];
};

JEnterRect: PROCEDURE = {
r: Rect;
ll,ur: Vector.Vec;
GetRect[@r];
ll←Vector.Min[r.ll,r.ur]; ur←Vector.Max[r.ll,r.ur];
EnterPoint[dc,ll];
EnterPoint[dc,[ll.x,ur.y]];
EnterPoint[dc,ur];
EnterPoint[dc,[ur.x,ll.y]];
NewBoundary[dc];
};

JSetClip: PROCEDURE = {
StartAreaPath[dc];
JEnterRect;
SetClipArea[dc];
};

JClipArea: PROCEDURE = {
SetClipArea[dc];
};

JClippedClipArea: PROCEDURE = {
IntersectClipArea[dc];
};

JTranslate: PROCEDURE = {
p: Point;
GetPoint[@p];
Translate[dc,p];
};


JScale: PROCEDURE = {
p: Point;
GetPoint[@p];
Scale[dc,p];
};

JRotate: PROCEDURE = {
a: REAL;
a ← GetReal[];
Rotate[dc,a];
};

JSixPoint: PROCEDURE = {
f1,f2,f3,t1,t2,t3,o1,df1,df2,dt1,dt2:Point;
adet:REAL;
m:Vector.Matrix;
GetPoint[@t3];
GetPoint[@t2];
GetPoint[@t1];
GetPoint[@f3];
GetPoint[@f2];
GetPoint[@f1];
o1←Vector.Sub[t1,f1];
dt1←Vector.Sub[t2,t1];
df1←Vector.Sub[f2,f1];
dt2←Vector.Sub[t3,t1];
df2←Vector.Sub[f3,f1];
adet←1.0/Vector.Cross[df1,df2];
m.a11←(dt1.x*df2.y-dt2.x*df1.y)*adet;
m.a12←(df1.x*dt2.x-df2.x*dt1.x)*adet;
m.a21←(dt1.y*df2.y-dt2.y*df1.y)*adet;
m.a22←(df1.x*dt2.y-df2.x*dt1.y)*adet;
Translate[dc,o1];
Concatenate[dc,m]
};

JConcat: PROCEDURE = {
m: Vector.Matrix;
m.a22 ← GetReal[];
m.a21 ← GetReal[];
m.a12 ← GetReal[];
m.a11 ← GetReal[];
Concatenate[dc,m];
};


JLineWidth: PROCEDURE = {
w: REAL ← GetReal[];
SetLineWidth[dc,w];
};

JGetPos: PROCEDURE = {
p: Point←GetPosition[dc];
PutPoint[@p];
};

JMoveTo: PROCEDURE = {
p: Point;
GetPoint[@p];
MoveTo[dc,p];
};

JDrawTo: PROCEDURE = {
p: Point;
GetPoint[@p];
DrawTo[dc,p];
};

JDot: PROCEDURE = {
p: Point;
GetPoint[@p];
MoveTo[dc,p];
DrawTo[dc,p];
};

JRelMoveTo: PROCEDURE = {
p: Point;
GetPoint[@p];
RelMoveTo[dc,p];
};

JRelDrawTo: PROCEDURE = {
p: Point;
GetPoint[@p];
RelDrawTo[dc,p];
};

JDrawBoxArea: PROCEDURE = {
r: Rect;
GetRect[@r];
DrawRectangle[dc,r.ll,r.ur];
};

JDrawScreenArea: PUBLIC PROCEDURE = {
DrawScreenArea[dc];
};

JSetPaint: PROCEDURE = {
f: INTEGER;
p: PaintingFunction;
f←PopInteger[];
SELECT f FROM
0 => p←paint;
1 => p←replace;
2 => p←invert;
3 => p←erase;
ENDCASE => p←paint;
SetPaint[dc,p];
};

JSetTexture: PROCEDURE = {
t: CARDINAL;
t←LOOPHOLE[PopInteger[],CARDINAL];
SetTexture[dc,t];
};

JSetColor: PROCEDURE = {
h,s,b: CARDINAL;
b←LOOPHOLE[PopInteger[],CARDINAL];
s←LOOPHOLE[PopInteger[],CARDINAL];
h←LOOPHOLE[PopInteger[],CARDINAL];
SetColor[dc,Color[h,s,b]];
};

JErase: PROCEDURE = {
PushContext[dc];
SetTexture[dc,white];
SetPaint[dc,replace];
DrawScreenArea[dc];
PopContext[dc];
};

Coords: TYPE = MACHINE DEPENDENT RECORD[x,y: INTEGER];
mouse: POINTER TO Coords = LOOPHOLE[424B];
cursor: POINTER TO Coords = LOOPHOLE[426B];

JGetTouch: PROCEDURE = {
UNTIL KeyDefs.Mouse.buttons = Red DO ENDLOOP;
UNTIL KeyDefs.Mouse.buttons = None DO ENDLOOP;
JGetMouse;
};

JMousePaint: PROCEDURE = {
r:Rect;
GetRect[@r];
DO
SELECT KeyDefs.Mouse.buttons FROM
= Red => {p: Point←ScreenCoordsToUser[mouse↑];
DrawRectangle[dc,Vector.Add[r.ll,p],Vector.Add[r.ur,p]];
};
= Yellow => {p: Point←ScreenCoordsToUser[mouse↑];
PushContext[dc];
SetTexture[dc,white];
SetPaint[dc,replace];
DrawRectangle[dc,Vector.Add[r.ll,p],Vector.Add[r.ur,p]];
PopContext[dc];
};
= Blue => EXIT;
ENDCASE => LOOP;
ENDLOOP;
};

JGetMouse: PROCEDURE = {
p: Point←ScreenCoordsToUser[mouse↑];
PutPoint[@p];
};

MouseToUser: PROCEDURE[x,y:INTEGER] = {
p: Point←ScreenCoordsToUser[[x,y]];
PutPoint[@p];
};

half: REAL=0.5;

ScreenCoordsToUser: PROCEDURE[c: Coords] RETURNS[Point] = {
x0,y0: INTEGER;
pt: Point;
[x0,y0]←AltoDevice.ScreenOrigin[];
pt←[(c.x-x0)+half,(c.y-y0)+half]; -- the center of the pixel
RETURN[ScreenPoint[mousedc,pt]];
};

JSetFont: PROCEDURE = {
fam: STRING ← [30];
size: CARDINAL;
size←LOOPHOLE[PopInteger[]];
PopString[fam];
IF pressdev = NIL THENSetFont[dc,MakeFont[fam],size] ELSE
{ph:POINTER TO PressDefs.PressFileDescriptor;
ph←LOOPHOLE[pressdev.data,PressDeviceImpl.DataRef].pressHandle;
PressDefs.SetFont[ph,fam,size,0,0];};
};

JDrawChar: PROCEDURE = {
s: STRING ← [1];
PopString[s];
IF pressdev = NIL THENDisplayChar[dc,s[0]] ELSE
{p: Vector.Vec;
ph:POINTER TO PressDefs.PressFileDescriptor;
ph←LOOPHOLE[pressdev.data,PressDeviceImpl.DataRef].pressHandle;
p←GetPosition[dc];
DrawRectangle[dc,p,p];
PressDefs.PutTextHere[ph,s];};
};

JDrawChars: PROCEDURE = {
s: STRING ← [256];
PopString[s];
IF pressdev = NIL THEN
{FOR i:CARDINAL IN[0..s.length) DO
DisplayChar[dc,s[i]];
ENDLOOP;}
ELSE
{p: Vector.Vec;
ph:POINTER TO PressDefs.PressFileDescriptor;
ph←LOOPHOLE[pressdev.data,PressDeviceImpl.DataRef].pressHandle;
p←GetPosition[dc];
DrawRectangle[dc,p,p];
PressDefs.PutTextHere[ph,s];};
};

JEraseChar: PROCEDURE = {
s: STRING ← [5];
PopString[s];
-- *** fix this
-- EraseChar[dc,s[0]];
};

JDrawString: PROCEDURE = {
s: STRING ← [256];
PopString[s];
IF pressdev = NIL THEN
{DisplayString[dc,s]}
ELSE
{p: Vector.Vec;
ph:POINTER TO PressDefs.PressFileDescriptor;
ph←LOOPHOLE[pressdev.data,PressDeviceImpl.DataRef].pressHandle;
p←GetPosition[dc];
DrawRectangle[dc,p,p];
PressDefs.PutTextHere[ph,s];};
};

JGetCharBox: PROCEDURE = {
s: STRING ← [5];
box: CharData;
PopString[s];
GetCharBox[dc,s[0],@box];
PushReal[box.size.x];
PushReal[box.size.y];
PushReal[box.origin.x];
PushReal[box.origin.y];
PushReal[box.width.x];
PushReal[box.width.y];
};

JGetStringBox: PROCEDURE = {
s: STRING ← [256];
box: CharData;
PopString[s];
GetStringBox[dc,s,@box];
PushReal[box.size.x];
PushReal[box.size.y];
PushReal[box.origin.x];
PushReal[box.origin.y];
PushReal[box.width.x];
PushReal[box.width.y];
};

JGetFontBox: PROCEDURE = {
box: CharData;
GetFontBox[dc,@box];
PushReal[box.size.x];
PushReal[box.size.y];
PushReal[box.origin.x];
PushReal[box.origin.y];
PushReal[box.width.x];
PushReal[box.width.y];
};

JEnterCubic: PROCEDURE = {
c: Coeffs;
GetPoint[@c.c3];
GetPoint[@c.c2];
GetPoint[@c.c1];
GetPoint[@c.c0];
EnterCubic[dc,@c];
};

JDrawCubic: PROCEDURE = {
c: Coeffs;
GetPoint[@c.c3];
GetPoint[@c.c2];
GetPoint[@c.c1];
GetPoint[@c.c0];
DrawCubic[dc,@c];
};

JBezierToCubic: PROCEDURE = {
b: Cubic.Bezier;
c: Coeffs;
GetPoint[@b.b3];
GetPoint[@b.b2];
GetPoint[@b.b1];
GetPoint[@b.b0];
c←Cubic.BezierToCoeffs[b];
PutPoint[@c.c0];
PutPoint[@c.c1];
PutPoint[@c.c2];
PutPoint[@c.c3];
};

JCubicToBezier: PROCEDURE = {
c: Coeffs;
b: Cubic.Bezier;
GetPoint[@c.c3];
GetPoint[@c.c2];
GetPoint[@c.c1];
GetPoint[@c.c0];
b←Cubic.CoeffsToBezier[c];
PutPoint[@b.b0];
PutPoint[@b.b1];
PutPoint[@b.b2];
PutPoint[@b.b3];
};

KnotArray: TYPE = DESCRIPTOR FOR ARRAY OF SplineDefs.FPCoords;

JEnterALSpline: PUBLIC PROCEDURE = {
knots: KnotArray;
n: CARDINAL←PopInteger[]; -- get number of knots.
knots←DESCRIPTOR[SplineMemoryDefs.Allocate[n*SIZE[SplineDefs.FPCoords]],n];
FOR i: CARDINAL DECREASING IN[0..n) DO
knots[i][SplineDefs.Y]←GetReal[];
knots[i][SplineDefs.X]←GetReal[];
ENDLOOP;
EnterSpline[knots,naturalAL];
SplineMemoryDefs.Free[BASE[knots]];
};

JEnterCyclicALSpline: PUBLIC PROCEDURE = {
knots: KnotArray;
n: CARDINAL←PopInteger[]+1; -- get number of knots.
knots←DESCRIPTOR[SplineMemoryDefs.Allocate[n*SIZE[SplineDefs.FPCoords]],n];
FOR i: CARDINAL DECREASING IN[1..n) DO
knots[i][SplineDefs.Y]←GetReal[];
knots[i][SplineDefs.X]←GetReal[];
ENDLOOP;
knots[0]←knots[n-1]; -- close the curve
EnterSpline[knots,cyclicAL];
SplineMemoryDefs.Free[BASE[knots]];
};

EnterSpline: PROCEDURE[knots: KnotArray, type: SplineDefs.SplineType] = {
allcoeffs: DESCRIPTOR FOR ARRAY OF SplineDefs.Coeffs;
allcoeffs ← SplineDefs.MakeSpline[knots,type];
FOR i: CARDINAL IN[0..LENGTH[allcoeffs]) DO
OPEN SplineDefs;
cf: Cubic.Coeffs←[
c0:[allcoeffs[i].t0[X],allcoeffs[i].t0[Y]],
c1:[allcoeffs[i].t1[X],allcoeffs[i].t1[Y]],
c2:[allcoeffs[i].t2[X],allcoeffs[i].t2[Y]],
c3:[allcoeffs[i].t3[X],allcoeffs[i].t3[Y]]
];
EnterCubic[dc,@cf];
ENDLOOP;
SplineDefs.FreeCoeffs[allcoeffs];
};

GetBoundingBox: PROCEDURE[b: POINTER TO BoundingBox] = {
FOR i: CARDINAL IN[0..4) DO GetPoint[@b[i]] ENDLOOP;
};

PutBoundingBox: PROCEDURE[b: POINTER TO BoundingBox] = {
FOR i: CARDINAL IN[0..4) DO PutPoint[@b[i]] ENDLOOP;
};

JStartBoxing: PROCEDURE = {
InitBoxer[dc];
};

JStopBoxing: PROCEDURE = {
b: BoundingBox;
StopBoxer[dc,@b];
PutBoundingBox[@b];
};

JPushBox: PROCEDURE = {
b: BoundingBox;
GetBoundingBox[@b];
PushClipBox[dc,@b];
};

JPopBox: PROCEDURE = {
PopClipBox[dc];
};

JVisible: PROCEDURE = {
PushBoolean[Visible[dc]];
};

JStartPath: PROCEDURE = {
StartAreaPath[dc];
};

JStartEOPath: PROCEDURE = {
StartAreaPath[dc,TRUE];
};

JEnterPoint: PROCEDURE = {
p: Point;
GetPoint[@p];
EnterPoint[dc,p];
};

JNewBoundary: PROCEDURE = {
NewBoundary[dc];
};

JDrawArea: PROCEDURE = {
DrawArea[dc];
};


-- the following are the SDFont interfaces;

OpenSDFile: PROCEDURE = {
s:STRING ←[64];
PopString[s];
BcplFontFileDefs.OpenSDFontFile[s];
};

CloseSDFile: PROCEDURE = {
BcplFontFileDefs.CloseSDFontFile[];
};

DrawSDChar: PROCEDURE = {
Move: PROC[v: POINTER TO Vec] = { MoveTo[dc,v↑] };
Draw: PROC[v: POINTER TO Vec] = { DrawTo[dc,v↑] };
Cubic: PROC[c: POINTER TO Coeffs] = { DrawCubic[dc,c] };
s:STRING←[8]; PopString[s];
PushReal[DoSDChar[s[0],Move,Draw,Cubic]];
};

EnterSDChar: PROCEDURE = {
Move: PROC[v: POINTER TO Vec] = { NewBoundary[dc]; EnterPoint[dc,v↑] };
Draw: PROC[v: POINTER TO Vec] = { EnterPoint[dc,v↑] };
Cubic: PROC[c: POINTER TO Coeffs] = { EnterCubic[dc,c] };
s:STRING←[8]; PopString[s];
PushReal[DoSDChar[s[0],Move,Draw,Cubic]];
};

tscp,scp:BcplFontFileDefs.SplineCommandPtr;
sdp:BcplFontFileDefs.SplineDataPtr;
pos: Vec;

ReturnSDChar: PROCEDURE = {
s:STRING←[8]; PopString[s];
[sdp,scp]←BcplFontFileDefs.GetSplineCommands[
s[0], SystemDefs.AllocateHeapNode];
tscp←scp;
pos←Vec[0,0];
};


GetSDCommand: PROCEDURE =
{Move: PROC[v: POINTER TO Vec] =
{ PushReal[v.x]; PushReal[v.y]; PushString["move"];};
Draw: PROC[v: POINTER TO Vec] =
{ PushReal[v.x]; PushReal[v.y]; PushString["draw"]; };
Cubic: PROC[c: POINTER TO Coeffs] = {
PushReal[c.c0.x]; PushReal[c.c0.y];
PushReal[c.c1.x]; PushReal[c.c1.y];
PushReal[c.c2.x]; PushReal[c.c2.y];
PushReal[c.c3.x]; PushReal[c.c3.y];
PushString["cubic"];
};

IF scp # NIL THEN {
WITH scp SELECT FROM
MoveTo => { pos←[x,y]; Move[@pos]; PushBoolean[TRUE];};
DrawTo => { pos←[x,y]; Draw[@pos]; PushBoolean[TRUE]; };
DrawCurve => {
c: Coeffs←[c3:[x2,y2],c2:[x1,y1],c1:[x0,y0],c0:pos];
Cubic[@c]; pos←[pos.x+x0+x1+x2, pos.y+y0+y1+y2];
PushBoolean[TRUE];
};
NewObject => NULL;
EndDefinition => {
scp←tscp;
UNTIL (scp←tscp) = NIL DO
tscp←scp.next;
SystemDefs.FreeHeapNode[scp];
ENDLOOP;
PushBoolean[FALSE];
};
ENDCASE;
scp←scp.next;
}ELSE{
scp←tscp;
UNTIL (scp←tscp) = NIL DO
tscp←scp.next;
SystemDefs.FreeHeapNode[scp];
ENDLOOP;
PushBoolean[FALSE];
};
RETURN};

DoSDChar: PROCEDURE[char: CHARACTER,
Move: PROCEDURE[v: POINTER TO Vec],
Draw: PROCEDURE[v: POINTER TO Vec],
Cubic: PROCEDURE[c: POINTER TO Coeffs]
] RETURNS[width: REAL] = {
tscp,scp:BcplFontFileDefs.SplineCommandPtr;
sdp:BcplFontFileDefs.SplineDataPtr;
pos: Vec←[0,0];
[sdp,scp]←BcplFontFileDefs.GetSplineCommands[
char, SystemDefs.AllocateHeapNode];
tscp←scp;
UNTIL scp = NIL DO
WITH scp SELECT FROM
MoveTo => { pos←[x,y]; Move[@pos] };
DrawTo => { pos←[x,y]; Draw[@pos] };
DrawCurve => {
c: Coeffs←[c3:[x2,y2],c2:[x1,y1],c1:[x0,y0],c0:pos];
Cubic[@c]; pos←[pos.x+x0+x1+x2, pos.y+y0+y1+y2];
};
NewObject => NULL;
EndDefinition => EXIT;
ENDCASE;
scp←scp.next;
ENDLOOP;
width←sdp.xwidth;
scp←tscp;
UNTIL (scp←tscp) = NIL DO
tscp←scp.next;
SystemDefs.FreeHeapNode[scp];
ENDLOOP;
RETURN [width]};

JCViC:PROCEDURE ={
c:CHARACTER←LOOPHOLE[PopInteger[]];
s:STRING←[1];
s[0]←c;
s.length←1;
PushString[s];
RETURN;};

JSDHeight: PROCEDURE= {
tscp,scp:BcplFontFileDefs.SplineCommandPtr;
sdp:BcplFontFileDefs.SplineDataPtr;
width:REAL;
s:STRING←[64];
char:CHARACTER;
PopString[s];
char←s[0];
[sdp,scp]←BcplFontFileDefs.GetSplineCommands[
char, SystemDefs.AllocateHeapNode];
width←sdp.ywidth;
tscp←scp;
UNTIL (scp←tscp) = NIL DO
tscp←scp.next;
SystemDefs.FreeHeapNode[scp];
ENDLOOP;
PushReal[width];};

JSDWidth: PROCEDURE= {
tscp,scp:BcplFontFileDefs.SplineCommandPtr;
sdp:BcplFontFileDefs.SplineDataPtr;
width:REAL;
s:STRING←[64];
char:CHARACTER;
PopString[s];
char←s[0];
[sdp,scp]←BcplFontFileDefs.GetSplineCommands[
char, SystemDefs.AllocateHeapNode];
width←sdp.xwidth;
tscp←scp;
UNTIL (scp←tscp) = NIL DO
tscp←scp.next;
SystemDefs.FreeHeapNode[scp];
ENDLOOP;
PushReal[width];};

JSDBox: PROCEDURE= {
tscp,scp:BcplFontFileDefs.SplineCommandPtr;
sdp:BcplFontFileDefs.SplineDataPtr;
llx,lly,urx,ury:REAL;
s:STRING←[64];
char:CHARACTER;
PopString[s];
char←s[0];
[sdp,scp]←BcplFontFileDefs.GetSplineCommands[
char, SystemDefs.AllocateHeapNode];
llx←sdp.bbox;
lly←sdp.bboy;
urx←sdp.rightx;
ury←sdp.topy;
tscp←scp;
UNTIL (scp←tscp) = NIL DO
tscp←scp.next;
SystemDefs.FreeHeapNode[scp];
ENDLOOP;
PushReal[llx];
PushReal[lly];
PushReal[urx];
PushReal[ury];};

JOpenPress: PROCEDURE = {
pressfilename: STRING←[64];
PopString[pressfilename];
pressdev←PressDevice.NewPressDevice[pressfilename];
olddc←dc;
dc←NewContext[pressdev]
};

JDumpScreen:PROC =
{bm:AltoDevice.Bitmap;
s:STRING←[64];
PopString[s];
bm←AltoDevice.ScreenBitmap[];
PressDevice.DumpScreen[s,bm];
RETURN;
};

JClosePress: PROCEDURE = {
FreeContext[@dc];
dc←olddc;
pressdev←NIL;
};

JOpenPressFont: PROCEDURE = {
OPEN PressDeviceImpl;
ph:POINTER TO PressDefs.PressFileDescriptor;
ptsize,face,rotation:CARDINAL;
fontname: STRING←[64];
rotation←ABS[PopInteger[]];
face←ABS[PopInteger[]];
ptsize←ABS[PopInteger[]];
PopString[fontname];
IF pressdev = NIL THEN RETURN;
ph←LOOPHOLE[pressdev.data,PressDeviceImpl.DataRef].pressHandle;
PressDefs.SetFont[ph,fontname,ptsize,face,rotation];
};

JEncodeFace: PROCEDURE = {
OPEN PressDeviceImpl;
ph:POINTER TO PressDefs.PressFileDescriptor;
weight: STRING ← [1];
slope: STRING ← [1];
expansion: STRING←[1];
PopString[expansion];
PopString[slope];
PopString[weight];
IF pressdev = NIL THEN RETURN;
ph←LOOPHOLE[pressdev.data,PressDeviceImpl.DataRef].pressHandle;
PushInteger[PressDefs.EncodeFace[weight[0],slope[0],expansion[0]]];
};

JPutPressText: PROCEDURE = {
OPEN PressDeviceImpl;
p: Vector.Vec;
ph:POINTER TO PressDefs.PressFileDescriptor;
text: STRING←[256];
PopString[text];
IF pressdev = NIL THEN RETURN;
ph←LOOPHOLE[pressdev.data,PressDeviceImpl.DataRef].pressHandle;
p←GetPosition[dc];
DrawRectangle[dc,p,p];
PressDefs.PutTextHere[ph,text];
};

JSetEpsilon: PROCEDURE = {
e:REAL←GetReal[];
Cubic.SetEpsilon[e];
};


-- Initialization starts here

SplineDefs.InitSplines[
alloc: SystemDefs.AllocateHeapNode,
free: SystemDefs.FreeHeapNode
];

dev←AltoDevice.NewAltoDevice[AltoDevice.ScreenBitmap[]];
dc←NewContext[dev];
mousedc←dc;

SetMouseProc[JaMStream[],MouseToUser];

Register[".initdc"L,InitDC];
Register[".pushdc"L,PushDC];
Register[".pushbasedc"L,PushBaseDC];
Register[".popdc"L,PopDC];
Register[".setview"L,JSetVw];
Register[".translate"L,JTranslate];
Register[".scale"L,JScale];
Register[".rotate"L,JRotate];
Register[".sixpoint"L,JSixPoint];
Register[".concat"L,JConcat];
Register[".linewidth"L,JLineWidth];
Register[".getpos"L,JGetPos];
Register[".moveto"L,JMoveTo];
Register[".rmoveto"L,JRelMoveTo];
Register[".drawto"L,JDrawTo];
Register[".rdrawto"L,JRelDrawTo];
Register[".dot"L,JDot];
Register[".drawboxarea"L,JDrawBoxArea];
Register[".drawscreenarea"L,JDrawScreenArea];
Register[".paint"L,JSetPaint];
Register[".texture"L,JSetTexture];
Register[".color"L,JSetColor];
Register[".enterspline"L,JEnterALSpline];
Register[".entercspline"L,JEnterCyclicALSpline];
Register[".entercubic"L,JEnterCubic];
Register[".drawcubic"L,JDrawCubic];
Register[".beziertocubic"L,JBezierToCubic];
Register[".cubictobezier"L,JCubicToBezier];
Register[".touch"L,JGetTouch];
Register[".mousepaint"L,JMousePaint];
Register[".mouse"L,JGetMouse];
Register[".erase"L,JErase];
Register[".setfont"L,JSetFont];
Register[".drawchar"L,JDrawChar];
Register[".drawchars"L,JDrawChars];
Register[".erasechar"L,JEraseChar];
Register[".drawstring"L,JDrawString];
Register[".getcharbox"L,JGetCharBox];
Register[".getstringbox"L,JGetStringBox];
Register[".getfontbox"L,JGetFontBox];
Register[".initboxer"L,JStartBoxing];
Register[".stopboxer"L,JStopBoxing];
Register[".pushbox"L,JPushBox];
Register[".popbox"L,JPopBox];
Register[".visible"L,JVisible];
Register[".setclip"L,JSetClip];
Register[".cliparea"L,JClipArea];
Register[".clippedcliparea"L,JClippedClipArea];
Register[".startpath"L,JStartPath];
Register[".starteopath"L,JStartEOPath];
Register[".enterpoint"L,JEnterPoint];
Register[".newboundary"L,JNewBoundary];
Register[".enterrect"L,JEnterRect];
Register[".drawarea"L,JDrawArea];
Register[".opensd",OpenSDFile];
Register[".closesd",CloseSDFile];
Register[".drawsdchar",DrawSDChar];
Register[".sdcharwidth",JSDWidth];
Register[".sdcharheight",JSDHeight];
Register[".sdcharbox",JSDBox];
Register[".cvic",JCViC];
Register[".entersdchar",EnterSDChar];
Register[".opensdchar",ReturnSDChar];
Register[".sdcommand",GetSDCommand];
Register[".openpress",JOpenPress];
Register[".dumpscreen",JDumpScreen];
Register[".closepress",JClosePress];
Register[".setpressfont",JOpenPressFont];
Register[".encodeface",JEncodeFace];
Register[".presstext",JPutPressText];
Register[".setepsilon",JSetEpsilon];

}.