<> <> <> DIRECTORY Imager, ImagerBasic USING [Rectangle, State, StateRep], ImagerBridge USING [SetViewFromGraphicsContext], ImagerTransform USING [InverseTransform, Invert, TransformRectangle, TransformationRec, FromRec], Font, Real USING [LargestNumber], Graphics USING [Context], CGVector USING [Vec, Sub, Cross], Rope USING [ActionType, Match, Fetch, Cat, Map, Length, ROPE], ViewerOps USING[PaintViewer], ViewerClasses USING [Viewer], JaM USING [State, PopInt, PushReal, PopReal, PopRope, Register], JaMImager, JaMImagerContexts, JaMIPrivate; JaMImagerImpl: CEDAR MONITOR IMPORTS ImagerBridge, JaM, JaMImager, JP: JaMIPrivate, Imager, ImagerTransform, Font, CGVector, Rope, ViewerOps, JaMImagerContexts EXPORTS JaMImager, JaMIPrivate = { Vec: TYPE = CGVector.Vec; GProc: TYPE = JaMImagerContexts.GProc; FONT: TYPE = Imager.FONT; ROPE: TYPE = Rope.ROPE; State: TYPE = JaM.State; Info: TYPE = JP.Info; GetVec: PROCEDURE [state: State] RETURNS[Vec] = { y: REAL _ JaM.PopReal[state]; x: REAL _ JaM.PopReal[state]; RETURN[[x,y]]; }; GetPoint: PROCEDURE [state: State] RETURNS[x,y: REAL] = { y _ JaM.PopReal[state]; x _ JaM.PopReal[state]; RETURN[x,y] }; PutPoint: PROCEDURE[state: State, x,y: REAL] = { JaM.PushReal[state,x]; JaM.PushReal[state,y] }; Box: TYPE = RECORD[xmin,ymin,xmax,ymax,w,h: REAL]; GetBox: PROC [state: State] RETURNS[Box] = { b: Box; [b.xmax,b.ymax] _ GetPoint[state]; [b.xmin,b.ymin] _ GetPoint[state]; IF b.ymax< b.ymin THEN {t: REAL _ b.ymin; b.ymin _ b.ymax; b.ymax _ t}; IF b.xmax< b.xmin THEN {t: REAL _ b.xmin; b.xmin _ b.xmax; b.xmax _ t}; b.w _ b.xmax-b.xmin; b.h _ b.ymax-b.ymin; RETURN[b]; }; PutFontBox: PROCEDURE[state: State, b: Font.Box] = { PutPoint[state,b.xmin,b.ymin]; PutPoint[state,b.xmax,b.ymax]; }; ViewToUser: PUBLIC PROC[context: Imager.Context, vx,vy: REAL] RETURNS [x,y: REAL] = { transformation: Imager.Transformation _ context.state.T; [[x,y]] _ ImagerTransform.InverseTransform[p: [vx,vy], transform: transformation]; }; ViewToUserRectangle: PROC[context: Imager.Context, vBox: ImagerBasic.Rectangle] RETURNS [uBox: ImagerBasic.Rectangle] = { transformation: Imager.Transformation _ context.state.T; uBox _ ImagerTransform.TransformRectangle[rect: vBox, transform: ImagerTransform.Invert[transformation]]; }; Paint: PUBLIC ENTRY SAFE PROCEDURE [self: ViewerClasses.Viewer, context: Graphics.Context, whatChanged: REF ANY, clear: BOOL] = TRUSTED { ENABLE UNWIND => NULL; info: Info _ NARROW[self.data]; IF whatChanged=NIL THEN { -- reset context --a priori knowledge of World and Viewer coordinates makes this work ImagerBridge.SetViewFromGraphicsContext[info.vdc, context]; Imager.Reset[info.vdc]; Imager.ConcatT[info.vdc, Imager.pointsToMeters]; --we like to think in points info.vw _ self.cw; info.vh _ self.ch; } ELSE info.proc[info.vdc]; }; Painter: PUBLIC PROCEDURE[proc: PROC [Imager.Context], state: State] = { info: Info _ JP.GetInfo[state]; SetProc: PROC = TRUSTED {info.proc _ proc}; JaMImagerContexts.ForAllDCs[info.dcList,proc]; IF info.venabled THEN { SetProc[]; --safe version of info.proc _ proc; ViewerOps.PaintViewer[viewer: info.viewer, hint: client, whatChanged: info, clearClient: FALSE]; }; }; stateStack: LIST OF ImagerBasic.State; PushDC: PROCEDURE [state: State] = { info: Info _ JP.GetInfo[state]; new: ImagerBasic.State _ NEW[ImagerBasic.StateRep _ info.vdc.state^]; <> stateStack _ CONS[new,stateStack]; }; PopDC: PROCEDURE [state: State] = { info: Info _ JP.GetInfo[state]; old: ImagerBasic.State; IF stateStack#NIL THEN old _ stateStack.first ELSE RETURN; stateStack _ stateStack.rest; info.vdc.state.T _ old.T; info.vdc.state.priorityImportant_ old.priorityImportant; info.vdc.state.color_ old.color; info.vdc.state.noImage_ old.noImage; info.vdc.state.strokeWidth_ old.strokeWidth; info.vdc.state.strokeEnd_ old.strokeEnd; info.vdc.state.clipper _ old.clipper; }; JClipArea: PROCEDURE [state: State] = { info: Info _ JP.GetInfo[state]; paint: GProc ={Imager.ClipOutline[context: dc, outline: Imager.MakeOutline[info.trajectory]]}; Painter[paint,state]; }; JClipBox: PROCEDURE [state: State] = { paint: GProc ={Imager.ClipRectangle[dc, box.xmin, box.ymin, box.w, box.h]}; box: Box _ GetBox[state]; Painter[paint,state]; }; JClipXArea: PROCEDURE [state: State] = { info: Info _ JP.GetInfo[state]; paint: GProc ={Imager.ExcludeOutline[dc, Imager.MakeOutline[info.trajectory]]}; Painter[paint,state]; }; JClipXBox: PROCEDURE [state: State] = { paint: GProc ={Imager.ExcludeRectangle[dc, box.xmin, box.ymin, box.w, box.h]}; box: Box _ GetBox[state]; Painter[paint,state]; }; JTranslate: PROCEDURE [state: State] = { paint: GProc ={Imager.TranslateT[dc,tx,ty]}; tx,ty: REAL; [tx,ty]_GetPoint[state]; Painter[paint,state]; }; JScale: PROCEDURE [state: State] = { paint: GProc ={ Imager.Scale2T[dc,sx,sy]}; sx,sy: REAL; [sx,sy]_GetPoint[state]; Painter[paint,state]; }; JRotate: PROCEDURE [state: State] = { paint: GProc ={Imager.RotateT[dc,a]}; a: REAL _ JaM.PopReal[state]; Painter[paint,state]; }; JSixPoint: PROCEDURE [state: State] = { paint: GProc ={ Imager.TranslateT[dc,t1.x,t1.y]; Imager.ConcatT[dc,t.FromRec]; Imager.TranslateT[dc,-f1.x,-f1.y]; }; f1,f2,f3,t1,t2,t3,df1,df2,dt1,dt2: Vec; adet: REAL; t: ImagerTransform.TransformationRec _ [0,0,0,0,0,0]; t3_GetVec[state]; t2_GetVec[state]; t1_GetVec[state]; f3_GetVec[state]; f2_GetVec[state]; f1_GetVec[state]; dt1_CGVector.Sub[t2,t1]; df1_CGVector.Sub[f2,f1]; dt2_CGVector.Sub[t3,t1]; df2_CGVector.Sub[f3,f1]; adet_1.0/CGVector.Cross[df1,df2]; t.a_(dt1.x*df2.y-dt2.x*df1.y)*adet; --m11 t.d_(dt1.y*df2.y-dt2.y*df1.y)*adet; --m12 t.b_(df1.x*dt2.x-df2.x*dt1.x)*adet; --m21 t.e_(df1.x*dt2.y-df2.x*dt1.y)*adet; --m22 Painter[paint,state]; }; JConcat: PROCEDURE [state: State] = { paint: GProc ={Imager.ConcatT[dc,t.FromRec]}; t: ImagerTransform.TransformationRec _ [0,0,0,0,0,0]; t.e _ JaM.PopReal[state]; --m22 t.b _ JaM.PopReal[state]; --m21 t.d _ JaM.PopReal[state]; --m12 t.a _ JaM.PopReal[state]; --m11 Painter[paint,state]; }; <> JGetPos: PROCEDURE [state: State] = { paint: GProc ={[[x,y]] _ Imager.GetCP[dc]}; x,y: REAL; Painter[paint,state]; PutPoint[state,x,y]; }; JSetPos: PROCEDURE [state: State] = { paint: GProc ={Imager.SetXY[dc,[x,y]]}; x,y: REAL; [x,y] _ GetPoint[state]; Painter[paint,state]; }; JRelSetPos: PROCEDURE [state: State] = { paint: GProc ={ Imager.SetXYRel[dc,[x,y]]}; x,y: REAL; [x,y]_GetPoint[state]; Painter[paint,state]; }; JDrawTo: PROCEDURE [state: State] = { paint: GProc ={ x0,y0: REAL; [[x0,y0]] _ Imager.GetCP[dc]; Imager.MaskVector[dc,[x0,y0],[x,y]]; Imager.SetXY[dc,[x,y]]; }; x,y: REAL; [x,y]_GetPoint[state]; Painter[paint,state]; }; JRelDrawTo: PROCEDURE [state: State] = { paint: GProc ={ x0,y0: REAL; [[x0,y0]] _ Imager.GetCP[dc]; Imager.MaskVector[dc,[x0,y0],[x0+x,y0+y]]; Imager.SetXY[dc,[x0+x,y0+y]]; }; x,y: REAL; [x,y]_GetPoint[state]; Painter[paint,state]; }; JDrawBox: PROCEDURE [state: State] = { paint: GProc ={Imager.MaskRectangle[dc,box.xmin,box.ymin,box.w,box.h]}; box: Box _ GetBox[state]; Painter[paint,state]; }; JCover: PROCEDURE [state: State] = { info: Info _ JP.GetInfo[state]; paint: GProc ={ box: ImagerBasic.Rectangle _ ViewToUserRectangle[dc,[x:0, y:0, w: info.vw, h: info.vh]]; --only works for viewers Imager.MaskRectangle[dc, box.x, box.y, box.w, box.h]; }; Painter[paint,state]; }; Erase: PROCEDURE [state: State] = { info: Info _ JP.GetInfo[state]; paint: GProc ={ erase: SAFE PROC = TRUSTED { box: ImagerBasic.Rectangle _ ViewToUserRectangle[dc,[x:0, y:0, w: info.vw, h: info.vh]]; --only works for viewers Imager.SetColor[dc, Imager.white]; Imager.MaskRectangle[dc, box.x, box.y, box.w, box.h]; }; Imager.DoSaveAll[dc,erase]; }; FOR l: JaMImagerContexts.DCList _ info.dcList, l.next UNTIL l=NIL DO IF l.enabled THEN l.dc _ l.callMe[l.dc, erase]; ENDLOOP; JaMImager.Painter[paint,state]; }; JSetInvert: PROCEDURE [state: State] = { paint: GProc ={[] _ Imager.SetColor[dc, Imager.XOR]}; Painter[paint,state]; }; defaultPath: ROPE _ "Xerox/PressFonts/"; defaultFace: ROPE _ "/MRR"; JSetFont: PROCEDURE [state: State] = { size: REAL _ JaM.PopReal[state]; name: ROPE _ JaM.PopRope[state]; IF ~Rope.Match["*/*",name] THEN name _ Rope.Cat[defaultPath,name,defaultFace]; JP.GetInfo[state].font _ Imager.MakeFont[name,size]; }; JDrawChar: PROCEDURE [state: State] = { paint: GProc ={Imager.ShowChar[context: dc, char: char, font: info.font]}; info: Info _ JP.GetInfo[state]; char: CHAR _ Rope.Fetch[JaM.PopRope[state]]; Painter[paint,state]; }; JDrawText: PROCEDURE [state: State] = { paint: GProc ={Imager.ShowCharacters[context: dc, characters: rope, font: info.font]}; info: Info _ JP.GetInfo[state]; rope: ROPE _ JaM.PopRope[state]; Painter[paint,state]; }; JCharBox: PROCEDURE [state: State] = { PutFontBox[state, Font.BoundingBox[font: JP.GetInfo[state].font, char: Rope.Fetch[JaM.PopRope[state]]]]; }; JFontBox: PROCEDURE [state: State] = { PutFontBox[state, Font.FontBoundingBox[JP.GetInfo[state].font]]; }; JTextBox: PROCEDURE [state: State] = { PutFontBox[state, RopeBox[JP.GetInfo[state].font, JaM.PopRope[state]]]; }; JCharWidth: PROCEDURE [state: State] = { x,y: REAL; [[x,y]] _ Font.WidthVector[font: JP.GetInfo[state].font, char: Rope.Fetch[JaM.PopRope[state]]]; PutPoint[state,x,y]; }; JTextWidth: PROCEDURE [state: State] = { x,y: REAL; [x,y] _ RopeWidth[JP.GetInfo[state].font, JaM.PopRope[state]]; PutPoint[state,x,y]; }; RopeBox: PROC[font: FONT, rope: ROPE] RETURNS[ropeBox: Font.Box]= { collect: Rope.ActionType = TRUSTED { box: Font.Box _ Font.BoundingBox[font: font, char: c]; ropeBox.xmin _ MIN[ropeBox.xmin,box.xmin]; ropeBox.ymin _ MIN[ropeBox.ymin,box.ymin]; ropeBox.xmax _ MAX[ropeBox.xmax,box.xmax]; ropeBox.ymax _ MAX[ropeBox.ymax,box.ymax]; }; ropeBox _ [xmin: Real.LargestNumber, ymin: Real.LargestNumber, xmax: 0, ymax: 0]; [] _ Rope.Map[base: rope, action: collect, len: Rope.Length[rope]]; }; RopeWidth: PROC[font: FONT, rope: ROPE] RETURNS[wx,wy: REAL]= { collect: Rope.ActionType = TRUSTED { vec: Font.Pair _ Font.WidthVector[font: font, char: c]; wx _ wx+vec.x; wy _ wy+vec.y; }; wx _ wy _ 0; [] _ Rope.Map[base: rope, action: collect, len: Rope.Length[rope]]; }; JFlushPath: PROCEDURE [state: State] = { JP.GetInfo[state].trajectory _ NIL; }; JMoveTo: PROCEDURE [state: State] = { x,y: REAL; [x,y]_GetPoint[state]; JP.GetInfo[state].trajectory _ LIST[Imager.MoveTo[[x,y]]]; }; JMoveToNext: PROCEDURE [state: State] = { info: Info _ JP.GetInfo[state]; x,y: REAL; [x,y]_GetPoint[state]; info.trajectory _ CONS[Imager.MoveTo[[x,y]],info.trajectory]; }; JLineTo: PROCEDURE [state: State] = { info: Info _ JP.GetInfo[state]; x,y: REAL; [x,y]_GetPoint[state]; IF info.trajectory=NIL THEN info.trajectory _ LIST[Imager.MoveTo[[0,0]]]; info.trajectory.first _ Imager.LineTo[info.trajectory.first,[x,y]]; }; JCurveTo: PROCEDURE [state: State] = { info: Info _ JP.GetInfo[state]; x1,y1,x2,y2,x3,y3: REAL; [x3,y3]_GetPoint[state]; [x2,y2]_GetPoint[state]; [x1,y1]_GetPoint[state]; IF info.trajectory=NIL THEN info.trajectory _ LIST[Imager.MoveTo[[0,0]]]; info.trajectory.first _ Imager.CurveTo[info.trajectory.first,[x1,y1],[x2,y2],[x3,y3]]; }; JRectangle: PROCEDURE [state: State] = { box: Box _ GetBox[state]; paint: GProc = {Imager.MaskRectangle[dc, box.xmin,box.ymin,box.w,box.h]}; Painter[paint,state]; }; JDrawArea: PROCEDURE [state: State] = { info: Info _ JP.GetInfo[state]; paint: GProc = {Imager.MaskFill[dc, Imager.MakeOutline[info.trajectory]]}; Painter[paint,state]; }; JDrawStroke: PROCEDURE [state: State] = { info: Info _ JP.GetInfo[state]; paint: GProc = {Imager.MaskStroke[dc,info.trajectory.first,width,ends]}; i: INT _ JaM.PopInt[state]; width: REAL _ JaM.PopReal[state]; ends: Imager.StrokeEnd _ (IF i=1 THEN square ELSE IF i=2 THEN round ELSE butt); IF info.trajectory#NIL THEN Painter[paint,state]; }; JDrawStrokeClosed: PROCEDURE [state: State] = { info: Info _ JP.GetInfo[state]; paint: GProc = {Imager.MaskStrokeClosed[dc,info.trajectory.first,width]}; width: REAL _ JaM.PopReal[state]; IF info.trajectory#NIL THEN Painter[paint,state]; }; <> RegisterGraphics: PUBLIC PROC[state: State] = { JaM.Register[state,".pushdc",PushDC]; JaM.Register[state,".popdc",PopDC]; JaM.Register[state,".translate",JTranslate]; JaM.Register[state,".scale",JScale]; JaM.Register[state,".rotate",JRotate]; JaM.Register[state,".sixpoint",JSixPoint]; JaM.Register[state,".concat",JConcat]; JaM.Register[state,".getpos",JGetPos]; JaM.Register[state,".setpos",JSetPos]; JaM.Register[state,".rsetpos",JRelSetPos]; JaM.Register[state,".drawto",JDrawTo]; JaM.Register[state,".rdrawto",JRelDrawTo]; JaM.Register[state,".drawbox",JDrawBox]; JaM.Register[state,".cover",JCover]; JaM.Register[state,".erase",Erase]; JaM.Register[state,".setinvert",JSetInvert]; JaM.Register[state,".setfont",JSetFont]; JaM.Register[state,".drawchar",JDrawChar]; JaM.Register[state,".drawtext",JDrawText]; JaM.Register[state,".charbox",JCharBox]; JaM.Register[state,".textbox",JTextBox]; JaM.Register[state,".charwidth",JCharWidth]; JaM.Register[state,".textwidth",JTextWidth]; JaM.Register[state,".fontbox",JFontBox]; JaM.Register[state,".cliparea",JClipArea]; JaM.Register[state,".clipbox",JClipBox]; JaM.Register[state,".clipxarea",JClipXArea]; JaM.Register[state,".clipxbox",JClipXBox]; JaM.Register[state,".flushpath",JFlushPath]; JaM.Register[state,".moveto",JMoveTo]; JaM.Register[state,".movetonext",JMoveToNext]; JaM.Register[state,".lineto",JLineTo]; JaM.Register[state,".curveto",JCurveTo]; JaM.Register[state,".rect",JRectangle]; JaM.Register[state,".drawarea",JDrawArea]; JaM.Register[state,".drawstroke",JDrawStroke]; JaM.Register[state,".drawstrokeclosed",JDrawStrokeClosed]; }; }. JGetYMode: PROCEDURE [state: State] = { paint: GProc ={mode _ ImagerOps.GetYMode[dc]}; mode: ImagerOps.YMode; Painter[paint,state]; JaM.PushInteger[state, IF mode=topDown THEN 1 ELSE 0]; }; JSetYMode: PROCEDURE [state: State] = { mode: LONG INTEGER _ JaM.PopInt[state]; paint: GProc ={ImagerOps.SetYMode[dc,IF mode>0 THEN topDown ELSE bottomUp]}; Painter[paint,state]; }; JStartBoxing: PROCEDURE [state: State] = { <> <> }; JStopBoxing: PROCEDURE [state: State] = { <> <> <> }; JPushBox: PROCEDURE [state: State] = { <> <> <<**** temporarily removed ****>> }; JPopBox: PROCEDURE [state: State] = { <> <<**** temporarily removed ****>> }; PutBox: PROC[state: State, b: Box] = { PutPoint[state,b.xmin,b.ymin]; PutPoint[state,b.xmax,b.ymax]; }; JDrawEOArea: PROCEDURE [state: State] = { info: Info _ GetInfo[state]; paint: GProc = {Imager.DrawArea[dc,info.trajectory,TRUE]}; Painter[paint,state]; }; GetRect: PROCEDURE [state: State] RETURNS[r: Rect] = { [r.xmax,r.ymax] _ GetPoint[state]; [r.xmin,r.ymin] _ GetPoint[state]; RETURN[r]; }; PutRect: PROCEDURE[state: State, r: Rect] = { PutPoint[state,r.xmin,r.ymin]; PutPoint[state,r.xmax,r.ymax]; }; JSetFat: PROCEDURE [state: State] = { paint: GProc ={[] _ Imager.SetFat[dc,b]}; b: BOOLEAN _ JaM.PopBoolean[state]; Painter[paint,state]; }; JSetOpaque: PROCEDURE [state: State] = { paint: GProc ={[] _ Imager.SetPaintMode[dc,IF b THEN opaque ELSE transparent]}; b: BOOLEAN _ JaM.PopBoolean[state]; Painter[paint,state]; }; JVisible: PROCEDURE [state: State] = { b: BOOLEAN; paint: GProc = {b _ Imager.Visible[dc]}; Painter[paint,state]; JaM.PushBoolean[state,b]; }; JScreenCoords: PROCEDURE [state: State] = { y: REAL _ JaM.PopReal[state]; x: REAL _ JaM.PopReal[state]; paint: GProc = {[x, y] _ Imager.UserToWorld[dc, x, y]}; -- get screen coordinates Painter[paint,state]; JaM.PushReal[state,x]; JaM.PushReal[state,y]; }; JUserCoords: PROCEDURE [state: State] = { y: REAL _ JaM.PopReal[state]; x: REAL _ JaM.PopReal[state]; paint: GProc = {[x, y] _ Imager.WorldToUser[dc, x, y]}; -- get user coordinates Painter[paint,state]; JaM.PushReal[state,x]; JaM.PushReal[state,y]; }; JKnot: PROCEDURE [state: State] = { info: Info _ GetInfo[state]; y: REAL _ JaM.PopReal[state]; x: REAL _ JaM.PopReal[state]; Spline.Knot[info.spline,x,y]; }; JSpline: PROCEDURE [state: State] = { info: Info _ GetInfo[state]; Spline.Enter[info.spline,info.trajectory,FALSE]; }; JCSpline: PROCEDURE [state: State] = { info: Info _ GetInfo[state]; Spline.Enter[info.spline,info.trajectory,TRUE]; }; <> JaM.Register[state,".setfat",JSetFat]; JaM.Register[state,".setopaque",JSetOpaque]; <> <> <> <> JaM.Register[state,".visible",JVisible]; JaM.Register[state,".setymode",JSetYMode]; JaM.Register[state,".getymode",JGetYMode]; JaM.Register[state,".screencoords",JScreenCoords]; JaM.Register[state,".usercoords",JUserCoords]; JaM.Register[state,".settarget",JSetTarget]; JaM.Register[state,".draweoarea",JDrawEOArea]; JaM.Register[state,".clipeoarea",JClipEOArea]; JaM.Register[state,".bitmap",JBitmap]; JaM.Register[state,".knot",JKnot]; JaM.Register[state,".spline",JSpline]; JaM.Register[state,".cspline",JCSpline];