-- TAGraphicsHacksImpl.mesa
-- Rick Beach, April 15, 1983 5:08 pm
-- Maureen Stone April 19, 1983 11:48 am
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],
JaMOps USING [defaultFrame],
Real,
TAGraphicsHacks,
TJaMGraphicsContexts USING [AddContext, EnableContext, DisableContext];
TAGraphicsHacksImpl: PROGRAM
IMPORTS CGArea, CGMatrix, CGStorage, Graphics, JaMFnsDefs, JaMOps, TJaMGraphicsContexts
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: 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]]];
};
InitBoxerDevice: PROCEDURE RETURNS [Graphics.Context] = {
RETURN [Graphics.NewContext[NewBoxerDevice[]]];
};
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
BeginBox[];
};
JEndBox: PROCEDURE[] = {
box: Graphics.Box;
box ← EndBox[];
JaMFnsDefs.PushReal[box.xmin];
JaMFnsDefs.PushReal[box.ymin];
JaMFnsDefs.PushReal[box.xmax];
JaMFnsDefs.PushReal[box.ymax];
};
BeginBox: PUBLIC PROCEDURE = {
init: PROC[dc: Graphics.Context] = {Graphics.Erase[dc]};
-- reset the boundsBox and and turn on the Boxer
TJaMGraphicsContexts.EnableContext[JaMOps.defaultFrame, $Boxer];
TJaMGraphics.Painter[init];
};
EndBox: PUBLIC PROCEDURE[] RETURNS[Graphics.Box] = {
-- Disable the context and return the bounding box on the JaM stack
TJaMGraphicsContexts.DisableContext[JaMOps.defaultFrame, $Boxer];
IF boundsBox=nullBoundsBox THEN RETURN[[0,0,0,0]]
ELSE RETURN[boundsBox] };
JaMFnsDefs.Register[".beginbox", JBeginBox];
JaMFnsDefs.Register[".endbox", JEndBox];
TJaMGraphicsContexts.AddContext[JaMOps.defaultFrame, InitBoxerDevice, $Boxer, FALSE];
}.