-- TJaMGraphicsImpl.mesa
-- Last changed by Bill Paxton, March 12, 1982 8:19 am
-- Last changed by Maureen Stone January 31, 1984 2:14:15 pm PST
-- Last changed by McGregor, September 13, 1982 1:44 pm
-- Last changed by Doug Wyatt, September 16, 1982 12:14 am
DIRECTORY
Graphics,
GraphicsOps,
GL
USING [ Start, End, Draw],
GraphicsBasic
USING [Vec],
CGVector
USING [Sub, Cross],
Rope
USING [
ROPE, Equal, Fetch, FromChar],
Spline
USING [Ref, Knot, Enter],
ViewerOps
USING[PaintViewer],
ViewerClasses
USING [Viewer],
JaM
USING [State, PopInt, PushInt, PushReal, PopReal, PopRope,
PushBool, PopBool, Register],
TJaMGraphics,
TJaMGraphicsContexts,
TJaMGraphicsInfo;
TJaMGraphicsImpl:
CEDAR MONITOR
IMPORTS JaM, TJaMGraphics, TJaMGraphicsInfo,
Graphics, GraphicsOps, CGVector, Rope, Spline, ViewerOps,
GL, TJaMGraphicsContexts
EXPORTS TJaMGraphics, TJaMGraphicsInfo = {
OPEN
J: JaM,
G: Graphics,
E: GraphicsOps,
Vector: CGVector, TJaMGraphics, TJaMGraphicsInfo,
TDC: TJaMGraphicsContexts;
Vec:
TYPE = GraphicsBasic.Vec;
GProc:
TYPE =
TDC.GProc;
ROPE:
TYPE = Rope.
ROPE;
Paint:
PUBLIC
ENTRY
SAFE
PROCEDURE [self: ViewerClasses.Viewer, context:
G.Context,
whatChanged:
REF
ANY, clear:
BOOL] =
TRUSTED {
ENABLE
UNWIND =>
NULL;
info: Info ←
NARROW[self.data];
IF whatChanged=
NIL
THEN {
-- reestablish context and erase
G.SetCP[context, 0, 0];
info.vinitdc ←
G.CopyContext[context];
info.vdc ←
G.CopyContext[info.vinitdc];
IF ~clear
THEN {
-- cannot simply call JErase because of monitor deadlock
mark:
G.Mark ←
G.Save[info.vdc];
G.SetColor[info.vdc,
G.white];
G.DrawBox[info.vdc,
G.GetBounds[info.vdc]];
G.Restore[info.vdc,mark] };
IF info.drawGL
THEN {
gl:
TDC.DCList ←
NIL;
FOR l:
TDC.DCList ← info.dcList, l.next
UNTIL l=
NIL
DO
IF l.name=$GList
THEN gl ← l;
ENDLOOP;
info.gl ←
GL.End[gl.dc];
IF info.gl#
NIL
THEN
GL.Draw[info.vdc,info.gl];
gl.dc ←
GL.Start[info.gl];
};
RETURN };
info.proc[info];
};
Painter:
PUBLIC
PROCEDURE[proc:
PROC [Graphics.Context], frame: J.State] = {
info: Info;
CallBack:
PROC [info: Info] = { proc[info.vdc] };
info ← GetInfo[frame];
TDC.ForAllDCs[info.dcList,proc];
IF info.venabled
THEN
TRUSTED {
info.proc ← CallBack;
ViewerOps.PaintViewer[viewer: info.viewer, hint: client, whatChanged: info, clearClient:
FALSE];
};
};
PushDC:
PROCEDURE [frame: JaM.State] = {
pushdc: GProc = {[] ←
G.Save[dc]};
Painter[pushdc,frame];
};
PopDC:
PROCEDURE [frame: J.State] = {
popdc: GProc = {[] ←
G.Restore[dc]};
Painter[popdc, frame];
};
GetVec:
PROCEDURE [frame: J.State]
RETURNS[Vec] = {
y:
REAL ←
J.PopReal[frame]; x:
REAL ←
J.PopReal[frame];
RETURN[[x,y]] };
GetPoint:
PROCEDURE [frame: J.State]
RETURNS[x,y:
REAL] = {
y ←
J.PopReal[frame]; x ←
J.PopReal[frame];
RETURN[x,y] };
PutPoint:
PROCEDURE[frame: J.State, x,y:
REAL] = {
J.PushReal[frame,x];
J.PushReal[frame,y] };
Rect:
TYPE =
RECORD[xmin,ymin,xmax,ymax:
REAL];
GetRect:
PROCEDURE [frame: J.State]
RETURNS[r: Rect] = {
[r.xmax,r.ymax] ← GetPoint[frame];
[r.xmin,r.ymin] ← GetPoint[frame];
RETURN[r];
};
PutRect:
PROCEDURE[frame: J.State, r: Rect] = {
PutPoint[frame,r.xmin,r.ymin];
PutPoint[frame,r.xmax,r.ymax];
};
JSetVw:
PROCEDURE [frame: J.State] = {
rt: Rect ← GetRect[frame];
rf: Rect ← GetRect[frame];
-- *** fix this
-- SetView[dc,@rf,@rt];
};
JClipArea:
PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
paint: GProc ={
G.ClipArea[self: dc, path: info.path]};
Painter[paint,frame];
};
JClipEOArea:
PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
paint: GProc ={
G.ClipArea[self: dc, path: info.path, parityFill:
TRUE]};
Painter[paint,frame];
};
JClipXArea:
PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
paint: GProc ={
G.ClipArea[self: dc, path: info.path, exclude:
TRUE]};
Painter[paint,frame];
};
JClipBox:
PROCEDURE [frame: J.State] = {
paint: GProc ={
G.ClipBox[dc, box]};
box:
G.Box ← GetBox[frame];
Painter[paint,frame];
};
JClipXBox:
PROCEDURE [frame: J.State] = {
paint: GProc ={
G.ClipBox[dc,box,
TRUE]};
box:
G.Box ← GetBox[frame];
Painter[paint,frame];
};
JTranslate:
PROCEDURE [frame: J.State] = {
paint: GProc ={
G.Translate[dc,tx,ty]};
tx,ty:
REAL;
[tx,ty]←GetPoint[frame];
Painter[paint,frame];
};
JScale:
PROCEDURE [frame: J.State] = {
paint: GProc ={
G.Scale[dc,sx,sy]};
sx,sy:
REAL;
[sx,sy]←GetPoint[frame];
Painter[paint,frame];
};
JRotate:
PROCEDURE [frame: J.State] = {
paint: GProc ={
G.Rotate[dc,a]};
a:
REAL ←
J.PopReal[frame];
Painter[paint,frame];
};
JSixPoint:
PROCEDURE [frame: J.State] = {
paint: GProc ={
G.Translate[dc,t1.x,t1.y];
G.Concat[dc,m11,m12,m21,m22];
G.Translate[dc,-f1.x,-f1.y];
};
f1,f2,f3,t1,t2,t3,df1,df2,dt1,dt2: Vec;
adet:
REAL;
m11,m12,m21,m22:
REAL;
t3←GetVec[frame];
t2←GetVec[frame];
t1←GetVec[frame];
f3←GetVec[frame];
f2←GetVec[frame];
f1←GetVec[frame];
dt1←Vector.Sub[t2,t1];
df1←Vector.Sub[f2,f1];
dt2←Vector.Sub[t3,t1];
df2←Vector.Sub[f3,f1];
adet𡤁.0/Vector.Cross[df1,df2];
m11←(dt1.x*df2.y-dt2.x*df1.y)*adet;
m12←(dt1.y*df2.y-dt2.y*df1.y)*adet;
m21←(df1.x*dt2.x-df2.x*dt1.x)*adet;
m22←(df1.x*dt2.y-df2.x*dt1.y)*adet;
Painter[paint,frame];
};
JConcat:
PROCEDURE [frame: J.State] = {
paint: GProc ={
G.Concat[dc,m11,m12,m21,m22]};
m11,m12,m21,m22:
REAL;
m22 ←
J.PopReal[frame];
m21 ←
J.PopReal[frame];
m12 ←
J.PopReal[frame];
m11 ←
J.PopReal[frame];
Painter[paint,frame];
};
--note multiple display context behavior
JGetPos:
PROCEDURE [frame: J.State] = {
paint: GProc ={[x,y]←
G.GetCP[dc]};
x,y:
REAL;
Painter[paint,frame];
PutPoint[frame,x,y];
};
JSetPos:
PROCEDURE [frame: J.State] = {
paint: GProc ={
G.SetCP[dc,x,y]};
x,y:
REAL; [x,y] ← GetPoint[frame];
Painter[paint,frame];
};
JRelSetPos:
PROCEDURE [frame: J.State] = {
paint: GProc ={
G.SetCP[dc,x,y,
TRUE]};
x,y:
REAL; [x,y]←GetPoint[frame];
Painter[paint,frame];
};
JDrawTo:
PROCEDURE [frame: J.State] = {
paint: GProc ={
G.DrawTo[dc,x,y]};
x,y:
REAL;
[x,y]←GetPoint[frame];
Painter[paint,frame];
};
JRelDrawTo:
PROCEDURE [frame: J.State] = {
paint: GProc ={
G.DrawTo[dc,x,y,
TRUE]};
x,y:
REAL;
[x,y]←GetPoint[frame];
Painter[paint,frame];
};
JDrawBox:
PROCEDURE [frame: J.State] = {
paint: GProc ={
G.DrawBox[dc,box]};
box:
G.Box ← GetBox[frame];
Painter[paint,frame];
};
JCover:
PROCEDURE [frame: J.State] = {
paint: GProc ={
G.DrawBox[dc,
G.GetBounds[dc]]};
Painter[paint,frame];
};
JSetInvert:
PROCEDURE [frame: J.State] = {
paint: GProc ={[] ←
G.SetPaintMode[dc, invert]};
Painter[paint,frame];
};
JSetFat:
PROCEDURE [frame: J.State] = {
paint: GProc ={[] ←
G.SetFat[dc,b]};
b:
BOOLEAN ←
J.PopBool[frame];
Painter[paint,frame];
};
JSetOpaque:
PROCEDURE [frame: J.State] = {
paint: GProc ={[] ←
G.SetPaintMode[dc,
IF b
THEN opaque
ELSE transparent]};
b:
BOOLEAN ←
J.PopBool[frame];
Painter[paint,frame];
};
JGetTouch:
PROCEDURE [frame: J.State] = {
mx,my:
REAL;
[mx,my] ← RealViewerMouse[frame,
TRUE];
PutPoint[frame,mx,my];
};
JGetMouse:
PROCEDURE [frame: J.State] = {
mx,my:
REAL;
[mx,my] ← RealViewerMouse[frame,
FALSE];
PutPoint[frame,mx,my];
};
JSetFont:
PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
info.text ← J.PopRope[frame];
FOR f: FontCache ← fontCache, f.next
UNTIL f =
NIL
DO
IF info.text.Equal[f.fontName,
FALSE]
THEN {
info.font ← f.fontRef;
RETURN;
};
ENDLOOP;
info.font ← G.MakeFont[info.text];
fontCache ← NEW[FontCacheRec ← [fontCache, info.text, info.font]];
};
FontCache: TYPE = REF FontCacheRec;
FontCacheRec:
TYPE =
RECORD [
next: FontCache,
fontName: Rope.ROPE,
fontRef: GraphicsOps.FontRef];
fontCache: FontCache ← NIL;
JGetYMode: PROCEDURE [frame: J.State] = {
paint: GProc ={mode ← E.GetYMode[dc]};
mode: E.YMode;
Painter[paint,frame];
J.PushInt[frame, IF mode=topDown THEN 1 ELSE 0];
};
JSetYMode: PROCEDURE [frame: J.State] = {
mode: LONG INTEGER ← J.PopInt[frame];
paint: GProc ={E.SetYMode[dc,IF mode>0 THEN topDown ELSE bottomUp]};
Painter[paint,frame];
};
JDrawChar: PROCEDURE [frame: J.State] = {
paint: GProc ={G.DrawChar[self: dc, char: Rope.Fetch[info.text], font: info.font]};
info: Info ← GetInfo[frame];
info.text ← J.PopRope[frame];
Painter[paint,frame];
};
JDrawText: PROCEDURE [frame: J.State] = {
paint: GProc ={G.DrawRope[self: dc, rope: info.text, font: info.font]};
info: Info ← GetInfo[frame];
info.text ← J.PopRope[frame];
Painter[paint,frame];
};
JCharBox: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
info.text ← J.PopRope[frame];
info.text ← Rope.FromChar[Rope.Fetch[info.text]];
PushTextBox[frame,info.text];
};
JTextBox: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
info.text ← J.PopRope[frame];
PushTextBox[frame,info.text];
};
JCharWidth: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
info.text ← J.PopRope[frame];
info.text ← Rope.FromChar[Rope.Fetch[info.text]];
PushTextWidth[frame,info.text];
};
JTextWidth: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
info.text ← J.PopRope[frame];
PushTextWidth[frame,info.text];
};
PushTextBox: PROCEDURE[frame: J.State, text: ROPE] = {
info: Info ← GetInfo[frame];
xmin,xmax,ymin,ymax: REAL;
[xmin: xmin, ymin: ymin, xmax: xmax, ymax: ymax] ← G.RopeBox[info.font,info.text];
J.PushReal[frame,xmin];
J.PushReal[frame,ymin];
J.PushReal[frame,xmax];
J.PushReal[frame,ymax];
};
PushTextWidth: PROCEDURE[frame: J.State, text: ROPE] = {
info: Info ← GetInfo[frame];
xw,yw: REAL;
[xw: xw, yw: yw] ← G.RopeWidth[info.font,info.text];
J.PushReal[frame,xw];
J.PushReal[frame,yw];
};
JFontBox: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
xmin,xmax,ymin,ymax: REAL;
[xmin: xmin, ymin: ymin, xmax: xmax, ymax: ymax] ← G.FontBox[info.font];
J.PushReal[frame,xmin];
J.PushReal[frame,ymin];
J.PushReal[frame,xmax];
J.PushReal[frame,ymax];
};
PutBox: PROC[frame: J.State, b: G.Box] = {
PutPoint[frame,b.xmin,b.ymin];
PutPoint[frame,b.xmax,b.ymax];
};
GetBox: PROC [frame: J.State] RETURNS[G.Box] = {
b: G.Box;
[b.xmax,b.ymax] ← GetPoint[frame];
[b.xmin,b.ymin] ← GetPoint[frame];
RETURN[b];
};
JStartBoxing: PROCEDURE [frame: J.State] = {
-- info: Info ← GetInfo[frame];
-- E.BeginBox[dc];
};
JStopBoxing: PROCEDURE [frame: J.State] = {
-- info: Info ← GetInfo[frame];
-- b: G.Box ← E.EndBox[dc];
-- PutBox[frame,b];
};
JPushBox: PROCEDURE [frame: J.State] = {
-- b: G.Box ← GetBox[frame];
-- G.PushClipBox[dc,b];
-- **** temporarily removed ****
};
JPopBox: PROCEDURE [frame: J.State] = {
-- G.PopClipBox[dc];
-- **** temporarily removed ****
};
JVisible: PROCEDURE [frame: J.State] = {
b: BOOLEAN;
paint: GProc = {b ← G.Visible[dc]};
Painter[paint,frame];
J.PushBool[frame,b];
};
JFlushPath: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
G.FlushPath[info.path];
};
JMoveTo: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
x,y: REAL; [x,y]←GetPoint[frame];
G.MoveTo[info.path,x,y];
};
JMoveToNext: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
x,y: REAL; [x,y]←GetPoint[frame];
G.MoveTo[info.path,x,y,FALSE];
};
JLineTo: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
x,y: REAL; [x,y]←GetPoint[frame];
G.LineTo[info.path,x,y];
};
JCurveTo: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
x1,y1,x2,y2,x3,y3: REAL;
[x3,y3]←GetPoint[frame];
[x2,y2]←GetPoint[frame];
[x1,y1]←GetPoint[frame];
G.CurveTo[info.path,x1,y1,x2,y2,x3,y3];
};
JRectangle: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
x0,y0,x1,y1: REAL;
[x1,y1]←GetPoint[frame];
[x0,y0]←GetPoint[frame];
G.Rectangle[info.path,x0,y0,x1,y1];
};
JDrawArea: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
paint: GProc = {G.DrawArea[dc, info.path]};
Painter[paint,frame];
};
JDrawEOArea: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
paint: GProc = {G.DrawArea[dc,info.path,TRUE]};
Painter[paint,frame];
};
JDrawStroke: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
paint: GProc = {G.DrawStroke[dc,info.path,width,FALSE,ends]};
i: INTEGER ← J.PopInt[frame];
width: REAL ← J.PopReal[frame];
ends: G.StrokeEnds ← (IF i=1 THEN square ELSE IF i=2 THEN round ELSE butt);
Painter[paint,frame];
};
JDrawStrokeClosed: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
paint: GProc = {G.DrawStroke[dc,info.path,width,TRUE]};
width: REAL ← J.PopReal[frame];
Painter[paint,frame];
};
JKnot: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
y: REAL ← J.PopReal[frame];
x: REAL ← J.PopReal[frame];
Spline.Knot[info.spline,x,y];
};
JSpline: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
Spline.Enter[info.spline,info.path,FALSE];
};
JCSpline: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
Spline.Enter[info.spline,info.path,TRUE];
};
bmw: CARDINAL = 250;
bmh: CARDINAL = 200;
GetBitmapSize: PUBLIC PROC RETURNS [w, h: CARDINAL] = {RETURN[bmw,bmh]};
JBitmap: PROCEDURE [frame: J.State] = {
info: Info ← GetInfo[frame];
paint: GProc = {E.DrawBitmap[dc,info.bitmap,bmw,bmh,0,0,0,bmh]};
Painter[paint,frame];
};
JSetTarget: PROC [frame: J.State] = {
info: Info ← GetInfo[frame];
b: BOOLEAN ← J.PopBool[frame];
paint: GProc = {E.SetTargetBitmap[dc,IF b THEN info.bitmap ELSE NIL]};
Painter[paint,frame];
};
JScreenCoords: PROCEDURE [frame: J.State] = {
y: REAL ← J.PopReal[frame];
x: REAL ← J.PopReal[frame];
paint: GProc = {[x, y] ← Graphics.UserToWorld[dc, x, y]}; -- get screen coordinates
Painter[paint,frame];
J.PushReal[frame,x];
J.PushReal[frame,y];
};
JUserCoords: PROCEDURE [frame: J.State] = {
y: REAL ← J.PopReal[frame];
x: REAL ← J.PopReal[frame];
paint: GProc = {[x, y] ← Graphics.WorldToUser[dc, x, y]}; -- get user coordinates
Painter[paint,frame];
J.PushReal[frame,x];
J.PushReal[frame,y];
};
-- Initialization starts here
RegisterGraphics: PUBLIC PROC[frame: J.State] = {
J.Register[frame,".pushdc",PushDC];
J.Register[frame,".popdc",PopDC];
-- J.Register[frame,".setview",JSetVw];
J.Register[frame,".translate",JTranslate];
J.Register[frame,".scale",JScale];
J.Register[frame,".rotate",JRotate];
J.Register[frame,".sixpoint",JSixPoint];
J.Register[frame,".concat",JConcat];
J.Register[frame,".getpos",JGetPos];
J.Register[frame,".setpos",JSetPos];
J.Register[frame,".rsetpos",JRelSetPos];
J.Register[frame,".drawto",JDrawTo];
J.Register[frame,".rdrawto",JRelDrawTo];
J.Register[frame,".drawbox",JDrawBox];
J.Register[frame,".cover",JCover];
J.Register[frame,".setinvert",JSetInvert];
J.Register[frame,".setfat",JSetFat];
J.Register[frame,".setopaque",JSetOpaque];
J.Register[frame,".touch",JGetTouch];
J.Register[frame,".mouse",JGetMouse];
J.Register[frame,".setfont",JSetFont];
J.Register[frame,".drawchar",JDrawChar];
J.Register[frame,".drawtext",JDrawText];
J.Register[frame,".charbox",JCharBox];
J.Register[frame,".textbox",JTextBox];
J.Register[frame,".charwidth",JCharWidth];
J.Register[frame,".textwidth",JTextWidth];
J.Register[frame,".fontbox",JFontBox];
-- J.Register[frame,".initboxer",JStartBoxing];
-- J.Register[frame,".stopboxer",JStopBoxing];
-- J.Register[frame,".pushbox",JPushBox];
-- J.Register[frame,".popbox",JPopBox];
J.Register[frame,".visible",JVisible];
J.Register[frame,".cliparea",JClipArea];
J.Register[frame,".clipbox",JClipBox];
J.Register[frame,".flushpath",JFlushPath];
J.Register[frame,".moveto",JMoveTo];
J.Register[frame,".movetonext",JMoveToNext];
J.Register[frame,".lineto",JLineTo];
J.Register[frame,".curveto",JCurveTo];
J.Register[frame,".rect",JRectangle];
J.Register[frame,".drawarea",JDrawArea];
J.Register[frame,".draweoarea",JDrawEOArea];
J.Register[frame,".drawstroke",JDrawStroke];
J.Register[frame,".drawstrokeclosed",JDrawStrokeClosed];
J.Register[frame,".knot",JKnot];
J.Register[frame,".spline",JSpline];
J.Register[frame,".cspline",JCSpline];
J.Register[frame,".bitmap",JBitmap];
J.Register[frame,".clipeoarea",JClipEOArea];
J.Register[frame,".clipxarea",JClipXArea];
J.Register[frame,".clipxbox",JClipXBox];
J.Register[frame,".getymode",JGetYMode];
J.Register[frame,".setymode",JSetYMode];
J.Register[frame,".settarget",JSetTarget];
J.Register[frame,".screencoords",JScreenCoords];
J.Register[frame,".usercoords",JUserCoords];
};
}.