-- JaMGraphicsImpl.mesa -- Last changed by Doug Wyatt, 19-Jan-82 15:20:56 DIRECTORY JaMGraphics USING [Mouse, Update], Graphics, GraphicsExtra, CGBasic USING [Vec], CGScreen USING [MouseToWorld], CGVector USING [Sub, Cross], Spline USING [Ref, New, Knot, Enter], JaMFnsDefs USING [PopInteger, PushInteger, PushReal, GetReal, PopString, PushBoolean, PopBoolean, Register], JaMTajo USING [SetMouseProc]; JaMGraphicsImpl: PROGRAM IMPORTS JaMFnsDefs, JaMTajo, JaMGraphics, Graphics, GraphicsExtra, CGVector, CGScreen, Spline EXPORTS JaMGraphics = { OPEN J: JaMFnsDefs, G: Graphics, E: GraphicsExtra, Vector: CGVector, Screen: CGScreen, JaMGraphics; Vec: TYPE = CGBasic.Vec; dc: G.Context←NIL; box: G.Box; image: G.ImageRef; GetDC: PUBLIC PROCEDURE RETURNS[G.Context] = { RETURN[dc] }; InitDC: PROCEDURE = { dc ← G.NewContext[]; G.ClipBox[dc,box]; }; PushDC: PROCEDURE = { [] ← G.Save[dc]; }; PopDC: PROCEDURE = { G.Restore[dc]; }; GetVec: PROCEDURE RETURNS[Vec] = { y: REAL ← J.GetReal[]; x: REAL ← J.GetReal[]; RETURN[[x,y]] }; GetPoint: PROCEDURE RETURNS[x,y: REAL] = { y ← J.GetReal[]; x ← J.GetReal[]; RETURN[x,y] }; PutPoint: PROCEDURE[x,y: REAL] = { J.PushReal[x]; J.PushReal[y] }; Rect: TYPE = RECORD[xmin,ymin,xmax,ymax: REAL]; GetRect: PROCEDURE RETURNS[r: Rect] = { [r.xmax,r.ymax] ← GetPoint[]; [r.xmin,r.ymin] ← GetPoint[]; RETURN[r]; }; PutRect: PROCEDURE[r: Rect] = { PutPoint[r.xmin,r.ymin]; PutPoint[r.xmax,r.ymax]; }; JSetVw: PROCEDURE = { rt: Rect ← GetRect[]; rf: Rect ← GetRect[]; -- *** fix this -- SetView[dc,@rf,@rt]; }; JClipArea: PROCEDURE = { G.ClipArea[dc]; }; JClipEOArea: PROCEDURE = { G.ClipArea[self: dc, parityFill: TRUE]; }; JClipXArea: PROCEDURE = { G.ClipArea[self: dc, exclude: TRUE]; }; JClipBox: PROCEDURE = { box: G.Box ← GetBox[]; G.ClipBox[dc,box]; }; JClipXBox: PROCEDURE = { box: G.Box ← GetBox[]; G.ClipBox[dc,box,TRUE]; }; JTranslate: PROCEDURE = { tx,ty: REAL; [tx,ty]←GetPoint[]; G.Translate[dc,tx,ty]; }; JScale: PROCEDURE = { sx,sy: REAL; [sx,sy]←GetPoint[]; G.Scale[dc,sx,sy]; }; JRotate: PROCEDURE = { a: REAL ← J.GetReal[]; G.Rotate[dc,a]; }; JSixPoint: PROCEDURE = { f1,f2,f3,t1,t2,t3,df1,df2,dt1,dt2: Vec; adet: REAL; xx,xy,yx,yy,tx,ty: REAL; t3←GetVec[]; t2←GetVec[]; t1←GetVec[]; f3←GetVec[]; f2←GetVec[]; f1←GetVec[]; [[tx,ty]]←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]; xx←(dt1.x*df2.y-dt2.x*df1.y)*adet; xy←(df1.x*dt2.x-df2.x*dt1.x)*adet; yx←(dt1.y*df2.y-dt2.y*df1.y)*adet; yy←(df1.x*dt2.y-df2.x*dt1.y)*adet; G.Translate[dc,tx,ty]; G.Concat[dc,xx,xy,yx,yy] }; JConcat: PROCEDURE = { xx,xy,yx,yy: REAL; yy ← J.GetReal[]; yx ← J.GetReal[]; xy ← J.GetReal[]; xx ← J.GetReal[]; G.Concat[dc,xx,xy,yx,yy]; }; JGetPos: PROCEDURE = { x,y: REAL; [x,y]←G.GetCP[dc]; PutPoint[x,y]; }; JMoveTo: PROCEDURE = { x,y: REAL; [x,y]←GetPoint[]; G.MoveTo[dc,x,y]; }; JDrawTo: PROCEDURE = { x,y: REAL; [x,y]←GetPoint[]; G.DrawTo[dc,x,y]; Update[]; }; JRelMoveTo: PROCEDURE = { x,y: REAL; [x,y]←GetPoint[]; G.MoveTo[dc,x,y,TRUE]; }; JRelDrawTo: PROCEDURE = { x,y: REAL; [x,y]←GetPoint[]; G.DrawTo[dc,x,y,TRUE]; Update[]; }; JDrawBox: PROCEDURE = { box: G.Box ← GetBox[]; G.DrawBox[dc,box]; Update[]; }; JCover: PROCEDURE = { G.DrawBox[dc,G.GetBounds[dc]]; Update[]; }; JSetInvert: PROCEDURE = { [] ← G.SetPaintMode[dc, invert]; }; JSetColor: PROCEDURE = { t: CARDINAL←LOOPHOLE[J.PopInteger[],CARDINAL]; G.SetColor[dc,t]; }; JSetFat: PROCEDURE = { b: BOOLEAN ← J.PopBoolean[]; [] ← G.SetFat[dc,b]; }; JSetOpaque: PROCEDURE = { b: BOOLEAN ← J.PopBoolean[]; [] ← G.SetPaintMode[dc,IF b THEN opaque ELSE transparent]; }; JErase: PROCEDURE = { mark: G.Mark ← G.Save[dc]; G.SetColor[dc,0]; JCover[]; G.Restore[dc,mark]; }; JGetTouch: PROCEDURE = { mx,my: INTEGER; [mx,my] ← Mouse[TRUE]; PutCoords[mx,my]; }; JGetMouse: PROCEDURE = { mx,my: INTEGER; [mx,my] ← Mouse[FALSE]; PutCoords[mx,my]; }; PutCoords: PROC[mx,my: INTEGER] = { x,y: REAL; [x,y] ← ScreenCoordsToUser[mx,my]; PutPoint[x,y]; }; MouseToUser: PROCEDURE[x,y:INTEGER] = { ux,uy: REAL; [ux,uy]←ScreenCoordsToUser[x,y]; PutPoint[ux,uy]; }; half: REAL=0.5; ScreenCoordsToUser: PROCEDURE[sx,sy: INTEGER] RETURNS[x,y: REAL] = { x0,y0: INTEGER; [x0,y0] ← Screen.MouseToWorld[sx,sy]; [x,y] ← G.WorldToUser[dc,x0,y0]; RETURN[x,y]; }; font: E.FontRef ← E.DefaultStrikeFont[]; text: REF TEXT ← NEW[TEXT[256]]; JSetFont: PROCEDURE = { J.PopString[LOOPHOLE[text]]; font ← E.NewStrikeFont[text]; }; JGetYMode: PROCEDURE = { mode: E.YMode ← E.GetYMode[dc]; J.PushInteger[IF mode=topDown THEN 1 ELSE 0]; }; JSetYMode: PROCEDURE = { mode: INTEGER ← J.PopInteger[]; E.SetYMode[dc,IF mode>0 THEN topDown ELSE bottomUp]; }; JDrawChar: PROCEDURE = { J.PopString[LOOPHOLE[text]]; IF text.length>0 THEN text.length ← 1; G.DrawText[self: dc, text: text, font: font]; Update[]; }; JDrawText: PROCEDURE = { J.PopString[LOOPHOLE[text]]; G.DrawText[self: dc, text: text, font: font]; Update[]; }; JCharBox: PROCEDURE = { J.PopString[LOOPHOLE[text]]; IF text.length>0 THEN text.length ← 1; PushTextBox[text]; }; JTextBox: PROCEDURE = { J.PopString[LOOPHOLE[text]]; PushTextBox[text]; }; JCharWidth: PROCEDURE = { J.PopString[LOOPHOLE[text]]; IF text.length>0 THEN text.length ← 1; PushTextWidth[text]; }; JTextWidth: PROCEDURE = { J.PopString[LOOPHOLE[text]]; PushTextWidth[text]; }; PushTextBox: PROCEDURE[text: REF READONLY TEXT] = { xmin,xmax,ymin,ymax: REAL; [xmin: xmin, ymin: ymin, xmax: xmax, ymax: ymax] ← G.TextBox[font,text]; J.PushReal[xmin]; J.PushReal[ymin]; J.PushReal[xmax]; J.PushReal[ymax]; }; PushTextWidth: PROCEDURE[text: REF READONLY TEXT] = { xw,yw: REAL; [xw: xw, yw: yw] ← G.TextWidth[font,text]; J.PushReal[xw]; J.PushReal[yw]; }; JFontBox: PROCEDURE = { xmin,xmax,ymin,ymax: REAL; [xmin: xmin, ymin: ymin, xmax: xmax, ymax: ymax] ← G.FontBox[font]; J.PushReal[xmin]; J.PushReal[ymin]; J.PushReal[xmax]; J.PushReal[ymax]; }; PutBox: PROC[b: G.Box] = { PutPoint[b.xmin,b.ymin]; PutPoint[b.xmax,b.ymax]; }; GetBox: PROC RETURNS[G.Box] = { b: G.Box; [b.xmax,b.ymax] ← GetPoint[]; [b.xmin,b.ymin] ← GetPoint[]; RETURN[b]; }; JStartBoxing: PROCEDURE = { G.BeginBox[dc]; }; JStopBoxing: PROCEDURE = { b: G.Box ← G.EndBox[dc]; PutBox[b]; }; JPushBox: PROCEDURE = { b: G.Box ← GetBox[]; -- G.PushClipBox[dc,b]; -- **** temporarily removed **** }; JPopBox: PROCEDURE = { -- G.PopClipBox[dc]; -- **** temporarily removed **** }; JVisible: PROCEDURE = { J.PushBoolean[G.Visible[dc]]; }; JLineTo: PROCEDURE = { x,y: REAL; [x,y]←GetPoint[]; G.LineTo[dc,x,y]; }; JCurveTo: PROCEDURE = { x1,y1,x2,y2,x3,y3: REAL; [x3,y3]←GetPoint[]; [x2,y2]←GetPoint[]; [x1,y1]←GetPoint[]; G.CurveTo[dc,x1,y1,x2,y2,x3,y3]; }; JRectangle: PROCEDURE = { x0,y0,x1,y1: REAL; [x1,y1]←GetPoint[]; [x0,y0]←GetPoint[]; G.Rectangle[dc,x0,y0,x1,y1]; }; JClose: PROCEDURE = { G.Close[dc]; }; JDrawArea: PROCEDURE = { G.DrawArea[dc]; Update[]; }; JDrawEOArea: PROCEDURE = { G.DrawArea[dc,TRUE]; Update[]; }; JDrawPath: PROCEDURE = { width: REAL ← J.GetReal[]; G.DrawPath[dc,width]; Update[]; }; spline: Spline.Ref ← Spline.New[]; JKnot: PROCEDURE = { y: REAL ← J.GetReal[]; x: REAL ← J.GetReal[]; Spline.Knot[spline,x,y]; }; JSpline: PROCEDURE = { Spline.Enter[spline,dc,FALSE]; }; JCSpline: PROCEDURE = { Spline.Enter[spline,dc,TRUE]; }; bitmap: E.BitmapRef ← NIL; bmw: CARDINAL = 250; bmh: CARDINAL = 200; JBitmap: PROCEDURE = { E.DrawBitmap[dc,bitmap,bmw,bmh,0,0,0,bmh]; Update[]; }; JSetTarget: PROC = { b: BOOLEAN ← J.PopBoolean[]; E.SetTargetBitmap[dc,IF b THEN bitmap ELSE NIL]; }; JNewAISImage: PROC = { J.PopString[LOOPHOLE[text]]; image ← E.NewAisImage[text]; }; JDrawImage: PROC = { IF image=NIL THEN RETURN; G.DrawImage[dc,image]; Update[]; }; -- Initialization starts here dc ← G.NewContext[]; box ← G.GetBounds[dc]; G.ClipBox[dc,box]; bitmap ← E.NewBitmap[bmw,bmh]; [] ← JaMTajo.SetMouseProc[MouseToUser]; J.Register[".initdc"L,InitDC]; J.Register[".pushdc"L,PushDC]; J.Register[".popdc"L,PopDC]; J.Register[".setview"L,JSetVw]; J.Register[".translate"L,JTranslate]; J.Register[".scale"L,JScale]; J.Register[".rotate"L,JRotate]; J.Register[".sixpoint"L,JSixPoint]; J.Register[".concat"L,JConcat]; J.Register[".getpos"L,JGetPos]; J.Register[".moveto"L,JMoveTo]; J.Register[".rmoveto"L,JRelMoveTo]; J.Register[".drawto"L,JDrawTo]; J.Register[".rdrawto"L,JRelDrawTo]; J.Register[".drawbox"L,JDrawBox]; J.Register[".cover"L,JCover]; J.Register[".setinvert"L,JSetInvert]; J.Register[".setcolor"L,JSetColor]; J.Register[".setfat"L,JSetFat]; J.Register[".setopaque"L,JSetOpaque]; J.Register[".touch"L,JGetTouch]; J.Register[".mouse"L,JGetMouse]; J.Register[".erase"L,JErase]; J.Register[".setfont"L,JSetFont]; J.Register[".drawchar"L,JDrawChar]; J.Register[".drawtext"L,JDrawText]; J.Register[".charbox"L,JCharBox]; J.Register[".textbox"L,JTextBox]; J.Register[".charwidth"L,JCharWidth]; J.Register[".textwidth"L,JTextWidth]; J.Register[".fontbox"L,JFontBox]; J.Register[".initboxer"L,JStartBoxing]; J.Register[".stopboxer"L,JStopBoxing]; J.Register[".pushbox"L,JPushBox]; J.Register[".popbox"L,JPopBox]; J.Register[".visible"L,JVisible]; J.Register[".cliparea"L,JClipArea]; J.Register[".clipbox"L,JClipBox]; J.Register[".lineto"L,JLineTo]; J.Register[".curveto"L,JCurveTo]; J.Register[".rect"L,JRectangle]; J.Register[".close"L,JClose]; J.Register[".drawarea"L,JDrawArea]; J.Register[".draweoarea"L,JDrawEOArea]; J.Register[".drawpath"L,JDrawPath]; J.Register[".knot"L,JKnot]; J.Register[".spline"L,JSpline]; J.Register[".cspline"L,JCSpline]; J.Register[".bitmap"L,JBitmap]; J.Register[".clipeoarea"L,JClipEOArea]; J.Register[".clipxarea"L,JClipXArea]; J.Register[".clipxbox"L,JClipXBox]; J.Register[".getymode"L,JGetYMode]; J.Register[".setymode"L,JSetYMode]; J.Register[".settarget"L,JSetTarget]; J.Register[".newaisimage"L,JNewAISImage]; J.Register[".drawimage"L,JDrawImage]; }.