-- TAGraphicsHacksImpl.mesa -- Rick Beach, June 30, 1982 10:15 pm -- Maureen Stone October 22, 1982 3:01 pm DIRECTORY CGArea USING [Empty, Ref, Remove], CGContext USING [Rep], CGDevice USING [Ref, Rep], CGMatrix USING [Make, Ref], CGSource USING [Ref], CGStorage USING [qZone], Graphics USING [Box, Context, NewContext], GraphicsBasic USING [Trap], JaMFnsDefs USING [PushReal, Register], TJaMGraphics USING [Painter], JaMOps USING [defaultFrame], Real, TAGraphicsHacks, TJaMGraphicsPrivate USING [EstablishNonViewerContext, ForgetNonViewerContext]; TAGraphicsHacksImpl: PROGRAM IMPORTS CGArea, CGMatrix, CGStorage, Graphics, JaMFnsDefs, TJaMGraphics, JaMOps, TJaMGraphicsPrivate EXPORTS GraphicsBasic, TAGraphicsHacks = { -- convince the world that I know what is in these opaque types DeviceObject: PUBLIC TYPE = CGDevice.Rep; ContextObject: PUBLIC TYPE = CGContext.Rep; -- a global bounds box boundsBox: Graphics.Box; nullBoundsBox: Graphics.Box = [Real.LargestNumber, Real.LargestNumber, -Real.LargestNumber, -Real.LargestNumber]; Data: TYPE = REF DataRep; DataRep: TYPE = RECORD [ matrix: CGMatrix.Ref _ NIL -- base transformation matrix ]; dataZone: ZONE = CGStorage.qZone; repZone: ZONE = CGStorage.qZone; NewBoxerDevice: PUBLIC PROCEDURE RETURNS[CGDevice.Ref] = { data: Data _ dataZone.NEW[DataRep]; data.matrix _ CGMatrix.Make[[1,0,0,1,0,0]]; boundsBox _ nullBoundsBox; RETURN[repZone.NEW[CGDevice.Rep _ [ GetMatrix: GetMatrix, GetBounds: GetBounds, Show: BoxerShow, GetRaster: BoxerGetRaster, data: data]]]; }; GetMatrix: SAFE PROC[self: CGDevice.Ref] RETURNS[CGMatrix.Ref] = TRUSTED { data: Data _ NARROW[self.data]; RETURN[data.matrix]; }; GetBounds: SAFE PROC[self: CGDevice.Ref] RETURNS[Graphics.Box] = TRUSTED { RETURN[[0.1, 0.1, 4000-.1, 4000-.1]]}; BoxerShow: SAFE PROC[self: CGDevice.Ref, area: CGArea.Ref, src: CGSource.Ref, map: CGMatrix.Ref] = TRUSTED { -- extract the bounding box from the area and update the context bbox UNTIL CGArea.Empty[area] DO trap: GraphicsBasic.Trap _ CGArea.Remove[area]; { OPEN boundsBox, trap; xmin _ MIN[xmin, xbotL]; xmin _ MIN[xmin, xtopL]; ymin _ MIN[ymin, ybot]; xmax _ MAX[xmax, xbotR]; xmax _ MAX[xmax, xtopR]; ymax _ MAX[ymax, ytop]}; ENDLOOP; }; BoxerGetRaster: SAFE PROC[self: CGDevice.Ref] RETURNS[LONG POINTER,CARDINAL] = TRUSTED { -- no raster for this device (sic!) RETURN[NIL,0]; }; JBeginBox: PROCEDURE[] = { -- JaM callable procedure to begin bounding boxing context: Graphics.Context _ Graphics.NewContext[NewBoxerDevice[]]; TJaMGraphicsPrivate.EstablishNonViewerContext[JaMOps.defaultFrame, context]; }; JEndBox: PROCEDURE[] = { -- JaM callable procedure to return the bounding box paint: PROC [context: Graphics.Context] = {box _ EndBox[context]}; box: Graphics.Box; TJaMGraphics.Painter[paint]; TJaMGraphicsPrivate.ForgetNonViewerContext[JaMOps.defaultFrame]; JaMFnsDefs.PushReal[box.xmin]; JaMFnsDefs.PushReal[box.ymin]; JaMFnsDefs.PushReal[box.xmax]; JaMFnsDefs.PushReal[box.ymax]; }; EndBox: PUBLIC PROCEDURE[self: Graphics.Context] RETURNS[Graphics.Box] = { -- reset the context device pointer and return the bounding box on the JaM stack IF boundsBox=nullBoundsBox THEN RETURN[[0,0,0,0]] ELSE RETURN[boundsBox] }; JaMFnsDefs.Register[".beginbox", JBeginBox]; JaMFnsDefs.Register[".endbox", JEndBox]; }.