-- GraphicsImpl.mesa -- Last edited by Doug Wyatt, September 14, 1982 4:38 pm DIRECTORY CGArea USING [New, Ref], CGBitmapDevice USING [New], CGClipper USING [Assign, Bounds, Copy, New, Ref, Rep, SetBox, TestPoint], CGContext USING [Ref, Rep, TouchClipper, TouchMatrix], CGDevice USING [Ref, Rep], CGFont USING [New, Ref, Rep], CGMatrix USING [Assign, Copy, Inv, Map, Ref, Rep], CGPath USING [CurveTo, LastPoint, LineTo, MoveTo, New, Rectangle, Reset], CGPrivate, -- USING almost everything CGReducer USING [New, Ref], CGSource USING [Ref, Rep], CGStorage USING [qZone], Graphics USING [black, Context, ContextRep, ErrorType, GraphicsProcs, WarningType], GraphicsBasic USING [Box, Color, FontRef, ImageRef, Mark, PaintMode, Path, Vec, YMode], GraphicsOps USING [BitmapRef], RealFns USING [CosDeg, SinDeg]; GraphicsImpl: CEDAR PROGRAM IMPORTS CGArea, CGBitmapDevice, CGClipper, CGContext, CGFont, CGMatrix, CGPath, CGPrivate, CGReducer, CGStorage, RealFns EXPORTS Graphics, GraphicsBasic, GraphicsOps = { OPEN GraphicsBasic; DeviceObject: PUBLIC TYPE = CGDevice.Rep; -- export to GraphicsBasic FontObject: PUBLIC TYPE = CGFont.Rep; -- export to GraphicsBasic Context: TYPE = Graphics.Context; ContextData: TYPE = CGContext.Ref; repZone: ZONE = CGStorage.qZone; srcZone: ZONE = CGStorage.qZone; procs: REF Graphics.GraphicsProcs _ repZone.NEW[Graphics.GraphicsProcs _ [ GetCP: CGPrivate.GetCP, SetCP: CGPrivate.SetCP, DrawTo: CGPrivate.DrawTo, DrawStroke: CGPrivate.DrawStroke, DrawArea: CGPrivate.DrawArea, DrawBox: CGPrivate.DrawBox, DrawImage: CGPrivate.DrawImage, Translate: CGPrivate.Translate, Concat: CGPrivate.Concat, WorldToUser: CGPrivate.WorldToUser, UserToWorld: CGPrivate.UserToWorld, SetColor: CGPrivate.SetColor, GetColor: CGPrivate.GetColor, SetPaintMode: CGPrivate.SetPaintMode, SetFat: CGPrivate.SetFat, GetDefaultFont: CGPrivate.GetDefaultFont, SetDefaultFont: CGPrivate.SetDefaultFont, DrawChars: CGPrivate.DrawChars, ClipArea: CGPrivate.ClipArea, ClipBox: CGPrivate.ClipBox, IsPointVisible: CGPrivate.IsPointVisible, IsRectangular: CGPrivate.IsRectangular, GetBounds: CGPrivate.GetBounds, Visible: CGPrivate.Visible, Save: CGPrivate.Save, Restore: CGPrivate.Restore, DrawBits: CGPrivate.DrawBits, UserToDevice: CGPrivate.UserToDevice, DeviceToUser: CGPrivate.DeviceToUser, GetYMode: CGPrivate.GetYMode, SetYMode: CGPrivate.SetYMode, DrawTexturedBox: CGPrivate.DrawTexturedBox, Disable: CGPrivate.Disable, MoveDeviceRectangle: CGPrivate.MoveDeviceRectangle ]]; -- Signals -- Warning: PUBLIC SIGNAL[type: Graphics.WarningType] = CODE; Error: PUBLIC ERROR[type: Graphics.ErrorType] = CODE; -- Creating new contexts -- NewContext: PUBLIC PROC[device: CGDevice.Ref] RETURNS[Context] = { d: ContextData _ repZone.NEW[CGContext.Rep _ [ device: NIL, -- output device cp: [0,0], -- current position matrix: NIL, -- current matrix clipper: NIL, -- current clipper reducer: NIL, -- reducer area: NIL, src: NIL, -- current source haveRaster: FALSE, boxing: FALSE, newbox: FALSE, -- boxing state bbox: NIL ]]; m: CGMatrix.Ref _ NIL; dbase: LONG POINTER _ NIL; drast: CARDINAL _ 0; IF device=NIL THEN device _ CGBitmapDevice.New[NIL,0,0]; -- the screen m _ device.GetMatrix[device]; -- world to device transformation d.device _ device; d.cp _ CGMatrix.Map[m,[0,0]]; d.matrix _ CGMatrix.Copy[m]; d.clipper _ CGClipper.New[1]; d.reducer _ CGReducer.New[8]; d.area _ CGArea.New[4]; CGClipper.SetBox[d.clipper,device.GetBounds[device]]; d.src _ srcZone.NEW[CGSource.Rep _ [type: const, fat: FALSE, mode: opaque, bps: 0, color: Graphics.black, xbase: NIL, xrast: 0, Get: NIL]]; IF device.GetRaster#NIL THEN { [dbase,drast] _ device.GetRaster[device] }; IF dbase#NIL THEN { d.dbase _ dbase; d.drast _ drast; d.haveRaster _ TRUE }; RETURN[repZone.NEW[Graphics.ContextRep _ [procs, d]]]; }; CopyContext: PUBLIC PROC[self: Context] RETURNS[Context] = { d: ContextData _ NARROW[self.data]; device: CGDevice.Ref _ d.device; copy: ContextData _ repZone.NEW[CGContext.Rep _ [ device: device, -- output device cp: d.cp, -- current position matrix: NIL, -- current matrix clipper: NIL, -- current clipper reducer: NIL, -- reducer area: NIL, src: NIL, -- current source boxing: FALSE, newbox: FALSE, -- boxing state bbox: NIL, haveRaster: d.haveRaster, dbase: d.dbase, drast: d.drast ]]; copy.matrix _ CGMatrix.Copy[d.matrix]; copy.clipper _ CGClipper.Copy[d.clipper]; copy.reducer _ CGReducer.New[8]; copy.area _ CGArea.New[4]; copy.src _ srcZone.NEW[CGSource.Rep _ d.src^]; RETURN[repZone.NEW[Graphics.ContextRep _ [self.procs, copy]]]; }; -- Procedures independent of data representation -- minPathSize: NAT = 4; NewPath: PUBLIC PROC[initialSize: INT _ 0] RETURNS[Path] = { size: NAT _ MIN[MAX[initialSize, minPathSize], LAST[NAT]]; path: Path _ CGPath.New[size]; RETURN[path] }; LastPoint: PUBLIC PROC[self: Path] RETURNS[x, y: REAL] = { v: Vec _ CGPath.LastPoint[self]; RETURN[v.x, v.y]; }; FlushPath: PUBLIC PROC[self: Path] = { CGPath.Reset[self]; }; MoveTo: PUBLIC PROC[self: Path, x, y: REAL, flush: BOOLEAN _ TRUE] = { IF flush THEN CGPath.Reset[self]; CGPath.MoveTo[self, [x, y]]; }; LineTo: PUBLIC PROC[self: Path, x, y: REAL] = { CGPath.LineTo[self, [x, y]]; }; CurveTo: PUBLIC PROC[self: Path, x1, y1, x2, y2, x3, y3: REAL] = { CGPath.CurveTo[self, [x1, y1], [x2, y2], [x3, y3]]; }; Rectangle: PUBLIC PROC[self: Path, x0, y0, x1, y1: REAL] = { CGPath.Rectangle[self, [x0, y0], [x1, y1]]; }; Rotate: PUBLIC PROC[self: Context, angle: REAL] = { cos, sin: REAL; eps: REAL = 1E-6; TRUSTED { cos _ RealFns.CosDeg[angle]; sin _ RealFns.SinDeg[angle] }; IF ABS[sin]0 THEN 1 ELSE -1) }; IF ABS[cos]0 THEN 1 ELSE -1) }; self.procs.Concat[self, cos,sin,-sin,cos]; }; Map: PUBLIC PROC[sc,dc: Context, sx,sy: REAL] RETURNS[dx,dy: REAL] = { wx, wy: REAL; [wx, wy] _ sc.procs.UserToWorld[sc, sx, sy]; [dx, dy] _ dc.procs.WorldToUser[dc, wx, wy]; }; BitmapRef: TYPE = GraphicsOps.BitmapRef; DrawBitmap: PUBLIC PROC[self: Context, bitmap: BitmapRef, w, h: CARDINAL, x, y: CARDINAL, xorigin, yorigin: INTEGER] = { w _ MIN[w, bitmap.width-(x _ MIN[x, bitmap.width])]; h _ MIN[h, bitmap.height-(y _ MIN[y, bitmap.height])]; TRUSTED { self.procs.DrawBits[self, LOOPHOLE[bitmap.base], bitmap.raster, 0, x, y, w, h, xorigin, yorigin] }; }; NewContextFromBitmap: PUBLIC PROC[bitmap: BitmapRef] RETURNS[Context] = TRUSTED { dev: CGDevice.Ref _ CGBitmapDevice.New[ base: LOOPHOLE[bitmap.base], raster: bitmap.raster, height: bitmap.height]; RETURN[NewContext[dev]]; }; MapperObject: PUBLIC TYPE = CGMatrix.Rep; -- export to GraphicsBasic ClipperObject: PUBLIC TYPE = CGClipper.Rep; -- export to GraphicsBasic GetMapper: PUBLIC PROC[self: Context] RETURNS[CGMatrix.Ref] = { ctx: ContextData _ NARROW[self.data]; m: CGMatrix.Ref _ ctx.matrix; RETURN[CGMatrix.Copy[m]]; }; SetMapper: PUBLIC PROC[self: Context, mapper: CGMatrix.Ref] = { ctx: ContextData _ NARROW[self.data]; m: CGMatrix.Ref _ ctx.matrix; CGContext.TouchMatrix[ctx]; CGMatrix.Assign[m,mapper]; }; GetClipper: PUBLIC PROC[self: Context] RETURNS[CGClipper.Ref] = { ctx: ContextData _ NARROW[self.data]; clipper: CGClipper.Ref _ ctx.clipper; RETURN[CGClipper.Copy[clipper]]; }; SetClipper: PUBLIC PROC[self: Context, clipper: CGClipper.Ref] = { ctx: ContextData _ NARROW[self.data]; CGContext.TouchClipper[ctx]; CGClipper.Assign[ctx.clipper,clipper]; }; TestVisible: PUBLIC PROC[mapper: CGMatrix.Ref, clipper: CGClipper.Ref, x,y: REAL] RETURNS[BOOLEAN] = { p: Vec _ CGMatrix.Map[mapper,[x,y]]; RETURN[CGClipper.TestPoint[clipper,p]]; }; TestBounds: PUBLIC PROC[mapper: CGMatrix.Ref, clipper: CGClipper.Ref] RETURNS[Box] = { box: Box _ CGClipper.Bounds[clipper]; m: CGMatrix.Ref _ mapper; result: Box; a,b,c,d: Vec; IF m.rectangular THEN { a _ CGMatrix.Inv[m,[box.xmin,box.ymin]]; c _ CGMatrix.Inv[m,[box.xmax,box.ymax]]; result.xmin _ MIN[a.x,c.x]; result.xmax _ MAX[a.x,c.x]; result.ymin _ MIN[a.y,c.y]; result.ymax _ MAX[a.y,c.y]; } ELSE { a _ CGMatrix.Inv[m,[box.xmin,box.ymin]]; b _ CGMatrix.Inv[m,[box.xmax,box.ymin]]; c _ CGMatrix.Inv[m,[box.xmax,box.ymax]]; d _ CGMatrix.Inv[m,[box.xmin,box.ymax]]; result.xmin _ MIN[a.x,b.x,c.x,d.x]; result.xmax _ MAX[a.x,b.x,c.x,d.x]; result.ymin _ MIN[a.y,b.y,c.y,d.y]; result.ymax _ MAX[a.y,b.y,c.y,d.y]; }; RETURN[result]; }; BeginBox: PUBLIC PROC[self: Context] = { ctx: ContextData _ NARROW[self.data]; SIGNAL Warning[notImplemented]; ctx.boxing _ ctx.newbox _ TRUE; }; EndBox: PUBLIC PROC[self: Context] RETURNS[Box] = { ctx: ContextData _ NARROW[self.data]; box: Box _ [0,0,0,0]; SIGNAL Warning[notImplemented]; ctx.boxing _ FALSE; RETURN[box]; }; UnsafeNewFont: PUBLIC UNSAFE PROC[lp: LONG POINTER] RETURNS[CGFont.Ref] = UNCHECKED { RETURN[CGFont.New[lp]] }; }. Κ– "Mesa" style˜Iprocš’ΟcNœΟk œ žœžœžœGžœ3žœžœžœ.žœKœ žœžœžœžœVžœSžœžœ"žœžœžœtžœ*žœžœžœœ žœžœœ žœ"žœžœžœžœ"žœΊ  œ žœžœžœ žœžœžœœΟn œžœžœžœ)žœžœœœ žœœ žœœ žœ œ žœ žœœžœžœ žœœ žœžœ žœžœžœ žœžœžœžœžœœ "œψžœ#žœ:žœžœžœžœžœ1žœžœžœ4žœžœ žœ+Ÿ œžœžœžœ!žœNžœ'œœ žœœ žœœ žœ œ žœ žœœ žœ žœœ žœωžœžœ žœ33œžœŸœžœžœžœžœžœžœžœžœžœ'žœ Ÿ œžœžœ žœžœ)žœŸ œžœžœ-Ÿœžœžœžœ žœžœžœžœ:Ÿœžœžœžœ+Ÿœžœžœ%žœBŸ œžœžœžœ;Ÿœžœžœžœžœ žœ žœAžœžœ žœžœžœžœ žœžœ žœžœžœžœ;ŸœžœžœžœžœžœžœqžœŸ œžœžœ+žœžœžœ žœžœžœžœžœ!žœHŸœžœžœžœ žœ7žœ@žœ(žœžœœžœžœœŸ œžœžœžœ(žœ/žœŸ œžœžœ?žœnŸ œžœžœžœ)žœ7žœ Ÿ œžœžœAžœ[Ÿ œžœžœ4žœžœžœ/žœ(Ÿ œžœžœ1žœožœžœožœžœžœžœžœΙžœ%žœ%žœ%žœžœŸœžœžœ)žœžœ6žœŸœžœžœžœžœ'žœ)žœžœ Ÿ œžœžœžœžœžœžœž œžœ˜šH—…—$(‘